1 Tous les questionnaires

1.1 Exploration du database

Sachant les problèmes qu’on a avec l’ID unique, pour l’analyse stat on sera obligé d’exclure tous les IDs non unique. Malheureusement la variable filière pour le “test 2” est impossible à reconstruire sans créer des doublons donc c’est le seul choix qu’on a pour l’analyse. Mais voyons quand même celui qui était notre point de départ.

A ce point là on a 866 quesitonnaires mais nous n’avons pas une idée précise de combien de sujets uniques on peut être certains d’avoir. Actuallement a 380 IDs differents mais du coup on a 106 doublons.

16 on peut les exclure parce que ils sont vides et 4 parce que l’ID est manquant, pour arriver à 850 questionnaires et 379 IDs. Mettons maintenant les doublons en évidence.

Comme tu peux le voir on semble avoir 48 IDs presents au moins 3 fois. Creusons plus loin pour voir si on identifie un groupe d’IDs problematique. Théoriquement, si les gens avaient respecté les régles pour la création de l’identifiant anonyme, l’identifiant devrait suivre le pattern suivant: 1 chiffre - 2 lettres - 2 chiffres.

Voyons pour combien de lignes ce pattern est respecté:

FALSE TRUE
44 806

Cela nous dit que même si on regarde seulement les gens qui ont respecté la procedure pour la création des IDs, on à tjrs des lignes de trop. D’abord, regardons les entrés des gens qui ont tapé un ID au pif (donc les “falses”).

Néanmoins, s’ils ont utilisé 2 fois le même identifiant aberrant on pourra quand même les apparier. Voyons donc les IDs qui apparaissent >2 fois. Les IDs aberrants qui apparaissent 2 fois on peut les utiliser, les IDs qui apparaissent qu’une seule fois, idem, on peut les garder pour la partie descriptive (carrément ils ne sera pas possible de les utiliser pour la comparaison avant-après).

On voit que le seul ID problematique parmi les aberrants est “12345”. Voyons les lignes qui correspondent à cet ID.

On semble avoir 1 IDE et 1 MG, qui ont un doublon de “2ème test”. Si on regarde avec attention la ligne 3 et 4 sont identiques, avec une “filière” différente. Si la ligne 3 et 4 étaient par exemple “IDE” et la ligne 5 et 6 étaient “medecine generale” on aurait identifié des doublons –> problème résolu. Mais dans ce cas on a des doublons ET 2 personnes qui ont rentré 2 fois le “2ème test” en changeant aussi de filière. Il est donc impossible de rattacher ces questionnaires à un “test 1”. Ce qui est très très bizarre, est que les lignes 3 et 5 sont IDENTIQUES aux lignes 4 et 6. Ce qu’on peut faire, est prendre la moyenne des lignes 3-5 et 4-6. Le même approche nous sera utile pour gérer les IDs non aberrants doublons qui sont les suivants:

A ce point, avant de passer à regarder l’ensemble des tests appariés, on peut quand meme jetter un coup d’œil à “test 1” et “test 2” séparément pour voir comment les score sont distribués.

1.2 Données manquantes

(#tab:all tests NAs)Nb de valeurs manquantes par questionnaire
Nb missing values frequency %
Post
0 395 93.16
1 20 4.72
2 4 0.94
3 1 0.24
4 2 0.47
5 2 0.47
Pre
0 376 88.26
1 33 7.75
2 10 2.35
3 2 0.47
4 1 0.23
5 3 0.70
6 1 0.23

1.3 Distribution “filière” (1er fichier)

1.4 Distribution score moyen du questionnaire

(#tab:all tests dispersionmeasures)Score - Tous tests confondus - Mesures de dispersion
vars n mean deviation_standard min max range ecart_type
Ensemble 1 850 6.229 0.823 1.11 7 5.89 0.028
pre 1 426 5.918 0.830 1.11 7 5.89 0.040
post 1 424 6.542 0.688 2.10 7 4.90 0.033
(#tab:all tests dispersionmeasures)score - 1er test - Mesures de dispersion by filière
filiere vars n mean deviation_standard min max range ecart_type
IDE 1 176 6.058 0.792 1.11 7 5.89 0.060
MKE 1 48 6.031 0.787 3.85 7 3.15 0.114
maieutique 1 25 5.818 0.881 3.25 7 3.75 0.176
medecine generale 1 99 5.677 0.894 3.42 7 3.58 0.090
orthophonie 1 29 6.044 0.599 4.60 7 2.40 0.111
pharmacie 1 51 5.777 0.840 2.74 7 4.26 0.118
NA 1 3 5.650 1.169 4.95 7 2.05 0.675

2 ID uniques

Prenons maintenant la population composée seulement par des IDs uniques (qui apparaissent au max 1 fois par test).

2.1 Population et distribution par filière

Nous avons un total de 325 sujets, repartis de la façon suivante. Attention, ceux ne sont pas encore les sujets qui ont fait les 2 tests, ceux ci sont tous les IDs qui apparaissent au max 1 fois par test.

(#tab:id uniques distribution par filiere)Repartition sujets par filière
filiere Nb sujet participants %
IDE 129 39.69
maieutique 18 5.54
medecine generale 75 23.08
MKE 41 12.62
orthophonie 20 6.15
pharmacie 34 10.46
NA 8 2.46
Total 325 100.00

La différence par rapport à la distribution précédente est presque invisible, ce qui est bien. Nous ne sommes pas en train d’introduire des biais comme involontairement sélectionner une sous-population spécifique. Voyons maintenant qui sont les 8 sujets sans filière:

Apparémment ce sont des gens qui ont fait seulement le 2ème test.

2.2 Données manquantes

Voyons sur tout l’ensemble de tests, combien de données manquantes on a. Ce sont des “vraies” données manquantes OU des “NSP” qui n’était pas pertinents pour la question et vraisemblablement pris pour des “Ne sait pas”.

Table 1: Nb de valeurs manquantes par questionnaire
Nb missing values Freq %
0 524 90.19
1 36 6.20
2 13 2.24
3 3 0.52
4 1 0.17
5 4 0.69

On voit que les tests sont bien complets globalement. Seulement 7 questionnaires ont >=3 valeurs manquantes.

2.3 Distribution score moyen

Table 2: Score - ID uniques - Mesures de dispersion
vars n mean deviation_standard min max range ecart_type
Ensemble 1 581 6.188 0.828 2.10 7 4.90 0.034
pre 1 315 5.899 0.809 2.74 7 4.26 0.046
post 1 266 6.530 0.714 2.10 7 4.90 0.044
Table 3: Score - ID uniques - Mesures de dispersion by filière
filiere vars n mean deviation_standard min max range ecart_type
IDE 1 128 6.051 0.680 3.00 7.00 4.00 0.060
MKE 1 40 6.013 0.804 3.85 7.00 3.15 0.127
maieutique 1 18 5.787 0.937 3.25 6.95 3.70 0.221
medecine generale 1 75 5.660 0.919 3.42 7.00 3.58 0.106
orthophonie 1 20 6.034 0.657 4.60 7.00 2.40 0.147
pharmacie 1 34 5.703 0.895 2.74 7.00 4.26 0.153

J’ai un peu reformatté le tableau suivant que j’avais déjà fait.

filiere id nb_questionnaires valeurs_manquantes Tests non apparies Tests apparies
IDE 129 (39.69%) 229 (39.41%) 52 (54.74%) 29 (47.54%) 100 (39.06%)
MKE 41 (12.62%) 72 (12.39%) 8 (8.42%) 10 (16.39%) 31 (12.11%)
maieutique 18 (5.54%) 34 (5.85%) 3 (3.16%) 2 (3.28%) 16 (6.25%)
medecine generale 75 (23.08%) 140 (24.1%) 26 (27.37%) 10 (16.39%) 65 (25.39%)
orthophonie 20 (6.15%) 36 (6.2%) 5 (5.26%) 4 (6.56%) 16 (6.25%)
pharmacie 34 (10.46%) 62 (10.67%) 1 (1.05%) 6 (9.84%) 28 (10.94%)
NA 8 (2.46%) 8 (1.38%) 0 (0%) NA (NA%) NA (NA%)
Total 325 (100%) 581 (100%) 95 (100%) 61 (100%) 256 (100%)

3 IDs appariés

3.1 Population et distribution par filière

(#tab:filtro questionari apparie) Population de tests appariés
filiere id nb_questionnaires valeurs_manquantes
IDE 100 (39.06%) 200 (39.06%) 46 (55.42%)
MKE 31 (12.11%) 62 (12.11%) 7 (8.43%)
maieutique 16 (6.25%) 32 (6.25%) 3 (3.61%)
medecine generale 65 (25.39%) 130 (25.39%) 22 (26.51%)
orthophonie 16 (6.25%) 32 (6.25%) 4 (4.82%)
pharmacie 28 (10.94%) 56 (10.94%) 1 (1.2%)
Total 256 (100%) 512 (100%) 83 (100%)

3.2 Données manquantes

(#tab:tests appariés NAs) Nb de valeurs manquantes par questionnaire
Nb missing values Freq %
0 463 90.43
1 31 6.05
2 11 2.15
3 2 0.39
4 1 0.20
5 4 0.78

3.3 Distribution score moyen

3.3.1 Par question

Table 4: Tests appariés - Mesures de dispersion
n mean deviation_standard min max range ecart_type
Ensemble 512 6.206 0.839 2.10 7 4.90 0.037
pre 256 5.885 0.825 2.74 7 4.26 0.052
post 256 6.527 0.723 2.10 7 4.90 0.045
## `summarise()` has grouped output by 'filiere'. You can override using the
## `.groups` argument.
Table 5: Tests appariés - Mesures de dispersion by filière
test n mean sd min max range se
IDE
post 100 6.680 0.685 2.10 7.00 4.90 0.069
pre 100 6.039 0.683 3.00 7.00 4.00 0.068
Maieutique
post 31 6.673 0.530 5.05 7.00 1.95 0.095
pre 31 5.920 0.861 3.85 6.90 3.05 0.155
Medecine generale
post 16 6.644 0.393 5.85 7.00 1.15 0.098
pre 16 5.854 0.931 3.25 6.95 3.70 0.233
MKE
post 65 6.217 0.884 4.00 7.00 3.00 0.110
pre 65 5.658 0.945 3.42 7.00 3.58 0.117
Orthophonie
post 16 6.639 0.363 5.95 7.00 1.05 0.091
pre 16 6.019 0.670 4.60 6.90 2.30 0.167
Pharmacie
post 28 6.407 0.718 4.65 7.00 2.35 0.136
pre 28 5.768 0.904 2.74 7.00 4.26 0.171

3.3.2 Par questionnaire

3.3.2.1 Par questionnaire by filière

4 Tests stat

4.1 Test de Wilcoxon sur données appariées

Pour realiser un test de student, une parmi les plusieurs conditions de validité est que la variable qu’on étudie doit suivre la loi normale: sa distribution a une forme en cloche simmetrique. Or, on a vu à la fin du chapitre 3 que ce n’est pas du tout le cas. Cela nous rend “impossible” (“” parce que en vrai je peux quand meme le lancer sans soucis le test et très probablement personne te demanderait si tu as verifié les conditions de validité du test) utiliser le t student et on va devoir “se contenter” d’un test non-parametrique (quand la variable étudie ne suit pas une distribution précise, comme la loi normale par example).

L’equivalent non parametrique du t student apparié est le test de rang signé de wilcoxon avec correction de continuité. Je me repète, le test du rang signé de Wilcoxon est un test statistique non paramétrique qui compare deux échantillons apparentés ou des mesures répétées sur un seul échantillon afin d’évaluer si les rangs moyens de leur population diffèrent (c’est-à-dire qu’il s’agit d’un test de différence par paires). Il peut être utilisé comme alternative au test t de Student lorsque la population ne peut pas être supposée normalement distribuée.

En statistique, le “rang” fait référence à la position d’une valeur particulière au sein d’un ensemble de données lorsqu’elles sont classées par ordre croissant ou décroissant.

Par exemple, considérons l’ensemble de données suivant : {3, 7, 1, 4, 6}. Si nous le classons par ordre croissant, nous obtenons {1, 3, 4, 6, 7}. Le “rang” de chaque nombre dans l’ensemble de données original est alors sa position dans l’ensemble de données ordonné. Ainsi, le rang de 3 est 2, le rang de 7 est 5, le rang de 1 est 1, le rang de 4 est 3 et le rang de 6 est 4.

Dans le cadre du test du rang signé de Wilcoxon, les différences entre des observations appariées sont classées en fonction de leur valeur absolue. Le signe de la différence est ensuite appliqué au rang. Cela permet au test de prendre en compte à la fois l’ampleur des différences (par le biais des rangs des différences absolues) et le sens des différences (par le biais des signes).

Pense à l’ECN: on veut comparer la performance des éléves de 2 lycées. Le test de wilcoxon pourrait nous aider à répondre à la question “est-ce que si le classement (rang) median des élèves d’un lycée X ou Y est meilleure que le classement (rang) median de l’autre.

Je vais lancer le test sur l’ensemble de la population et t’expliquer le résultat.

## 
##  Wilcoxon signed rank test with continuity correction
## 
## data:  paired_data$post and paired_data$pre
## V = 27545, p-value < 2.2e-16
## alternative hypothesis: true location shift is not equal to 0
  • “Test de rang signé de Wilcoxon avec correction de continuité” : Ceci indique le test spécifique utilisé. La partie “correction de continuité” est une technique permettant d’ajuster le test de rang signé de Wilcoxon pour tenir compte du fait que nous utilisons une version discrète d’une distribution continue.

  • “Données : paired_data$post et paired_data$pre” : Ceci spécifie les deux ensembles de mesures ou d’observations qui ont été comparés dans le test.

  • “V = 52171”: Il s’agit de la statistique du test. Pour le test du rang signé de Wilcoxon, il s’agit de la somme des rangs des différences positives (ou de la somme des rangs négatifs, selon le logiciel utilisé).

  • “p-value < 2.2e-16” : Il s’agit de la valeur p du test, qui est utilisée pour interpréter les résultats. Si la valeur p est inférieure au seuil de signification choisi (souvent 0,05), l’hypothèse nulle est rejetée. Dans ce cas, la valeur p est extrêmement faible, et il y a donc de bonnes raisons de rejeter l’hypothèse nulle.

  • “Hypothèse alternative : le véritable distance entre les 2 medianes n’est pas égal à 0” : Il s’agit de l’hypothèse alternative du test. Pour le test du rang signé de Wilcoxon, l’hypothèse nulle est que la médiane des différences entre les paires d’observations est égale à zéro. Cette hypothèse alternative indique que la véritable médiane des différences n’est pas nulle.

En termes simples, le test indique qu’il existe une différence statistiquement significative entre les mesures avant et après dans ces données appariées, avec une valeur p très faible (<0.001) fournissant une preuve solide contre l’hypothèse nulle.

Je vais faire la même chose pour chaque filière prise singulièrement.

filiere p.value method
medecine generale < 0.001 Wilcoxon signed rank test with continuity correction
IDE < 0.001 Wilcoxon signed rank test with continuity correction
maieutique < 0.001 Wilcoxon signed rank test with continuity correction
pharmacie 0.002 Wilcoxon signed rank test with continuity correction
orthophonie 0.006 Wilcoxon signed rank test with continuity correction
MKE < 0.001 Wilcoxon signed rank test with continuity correction

4.2 Test de permutation

## Observed test statistic: 0.6417188
## P-value: < 0.001

Voici comment fonctionne un test de permutation, étape par étape :

Formuler l’hypothèse : on commence par énoncer l’hypothèse nulle (H₀) et l’hypothèse alternative (H₁). L’hypothèse nulle suppose qu’il n’y a pas de différence entre les groupes, tandis que l’hypothèse alternative suggère qu’il y a une différence significative.

Combiner et mélanger les données : Prenez les mesures (hauteurs) des deux groupes et combinez-les en un seul ensemble de données. Ensuite, mélangez ou permutez au hasard les étiquettes (groupe A et groupe B) associées aux mesures. Ce mélange rompt toute association entre les groupes.

Repeter les étapes 2 et 3 : Répétez les étapes 2 et 3 plusieurs fois (par exemple, 1 000 fois ou plus) pour créer une distribution de statistiques de test sous l’hypothèse nulle. Chaque fois que vous mélangez les données et calculez la statistique de test, vous simulez ce qui se passerait s’il n’y avait pas de véritable différence entre les groupes.

Comparez la statistique de test observée : On compare la statistique de test observée (calculée à partir des données originales, non mélangées) à la distribution des statistiques de test obtenues à partir des permutations. Il s’agit essentiellement de se demander : “Quelle est l’ampleur de la statistique de test observée par rapport à ce que l’on pourrait attendre du seul hasard ?”

Calculer la valeur p : Calculez la valeur p en déterminant la proportion de statistiques de test permutées qui sont plus extrêmes (plus grandes ou plus petites) que la statistique de test observée. Cette valeur p représente la probabilité d’observer une statistique de test aussi extrême, ou plus extrême, que celle qu’on a obtenue, en supposant que l’hypothèse nulle est vraie. Une petite valeur p suggère qu’il est peu probable que la différence observée soit le fruit du hasard.

Sur la base de la valeur p et du niveau de signification qu’on a défini (habituellement α = 0,05), on décide de rejeter ou non l’hypothèse nulle. Si la valeur p est inférieure au seuil de signification, on rejete l’hypothèse nulle et concluez qu’il existe des preuves d’une différence significative entre les groupes.

C’est l’idée de base d’un test de permutation. En mélangeant au hasard les étiquettes des groupes et en comparant la statistique de test observée à la distribution des statistiques de test permutées, les tests de permutation permettent d’évaluer la probabilité d’observer la différence observée sous l’hypothèse nulle d’absence de différence. Il s’agit d’une technique qui ne repose pas sur des hypothèses strictes concernant la distribution des données, ce qui la rend applicable à un large éventail de scénarios. Donc on a pas le problème de la non-normalité comme avec le t student et on a pas le problème des ex aequo comme avec wilcoxon. Quand possible, il est préférable appliquer les autres tests parce qu’ils sont plus puissants.

5 Extras

Table 6: Nb réponses NSP par filière en pré-test
filiere NSP
IDE 38
MKE 5
maieutique 3
medecine generale 12
orthophonie 1
pharmacie 1
Table 6: Nb réponses NSP par question ET par filière en pré-test
question filiere n
s1q4 IDE 14
s1q4 MKE 1
s1q4 maieutique 1
s1q4 medecine generale 4
s1q4 orthophonie 1
s1q4 pharmacie 1
s1q5 MKE 1
s2q3 IDE 1
s3q1 IDE 3
s3q1 medecine generale 2
s3q2 IDE 8
s3q2 MKE 3
s3q2 maieutique 2
s3q2 medecine generale 3
s4q1 IDE 2
s4q2 IDE 2
s5q2 IDE 3
s5q3 IDE 1
s6q3 IDE 3
s6q3 medecine generale 1
s7q1 medecine generale 1
s7q2 IDE 1
s7q2 medecine generale 1
Table 6: Nb de questionnaires avec des NSP en pré-test
filiere n Frequence_absolue Frequence_relative_uniques_ID_par_filiere
IDE 22 57.89 % 17.05 %
MKE 4 10.53 % 9.76 %
maieutique 2 5.26 % 11.11 %
medecine generale 8 21.05 % 10.67 %
orthophonie 1 2.63 % 5 %
pharmacie 1 2.63 % 2.94 %
Table 6: Nb de questionnaires avec des NSP en post-test
filiere n Frequence_absolue Frequence_relative_uniques_ID_par_filiere
IDE 2 20 % 1.98 %
MKE 1 10 % 3.12 %
medecine generale 5 50 % 7.69 %
orthophonie 2 20 % 12.5 %
LS0tDQp0aXRsZTogICAgIlRow6hzZSAtIFJhY2hlbCBGcsOpYm91cmciDQpzdWJ0aXRsZTogIkNvbXBhcmFpc29uIGF2YW50LWFwcsOocyBuaXZlYXUgaW50ZXJkaXNjaXBsaW5hcml0w6kgY2hleiBsZXMgcHJvIGRlIHNhbnTDqSINCmF1dGhvcjogICAiRnJhbmNlc2NvIE1PTlRJIg0KZGF0ZTogICAgICJgciBTeXMudGltZSgpYCIgIyBBdXRvbWF0aWMgZGF0ZSBhbmQgdGltZQ0Kb3V0cHV0Og0KICAgIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjogDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgSXQgY2FuIGJlIGEgbGlzdCBvZg0KICAgICAgICBjb2xsYXBzZTogInNob3ciDQogICAgICAgIHRvYzogICAgICAgICB5ZXMgICAgICAgICMgVGFibGUgb2YgY29udGVudHMgKHRvYyk6IHllcyBubw0KICAgICAgICB0b2NfZmxvYXQ6ICAgeWVzICAgICAgICAjIHllcyBubw0KICAgICAgICB0b2NfZGVwdGg6ICAgNSAgICAgICAgICAgICAgIyAxIDIgMyA0IDUNCiAgICAgICAgaGlnaGxpZ2h0IDogcHlnbWVudHMgICAgICAjIGRlZmF1bHQgdGFuZ28ga2F0ZSBtb25vY2hyb21lIGVzcHJlc3NvIHB5Z21lbnRzLi4uDQogICAgICAgIGhpZ2hsaWdodF9kb3dubGl0IDogVHJ1ZSAgICAgICMgVFJVRSB0byB1c2UgdGhlIGRvd25saXQgcGFja2FnZSBhcyBzeW50YXggaGlnaGxpZ2h0IGVuZ2luZSB0byBoaWdobGlnaHQgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGlubGluZSBjb2RlIGFuZCBSIGNvZGUgY2h1bmtzIChpbmNsdWRpbmcgcHJvdmlkaW5nIGh5cGVybGlua3MgdG8gZnVuY3Rpb24gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGRvY3VtZW50YXRpb24pLiBUaGUgcGFja2FnZSBuZWVkcyB0byBiZSBpbnN0YWxsZWQgdG8gdXNlIHRoaXMgZmVhdHVyZS4NCiAgICAgICAgY29kZV9mb2xkaW5nOiAgICAiaGlkZSIgICAgICMgbm9uZSBzaG93IGhpZGUNCiAgICAgICAgY29kZV9kb3dubG9hZDogICB5ZXMgICAgICAgICMgeWVzIG5vDQogICAgICAgIGZpZ19jYXB0aW9uOiB5ZXMgICAgICAgICMgeWVzIG5vDQogICAgICAgIGZpZ193aWR0aCA6IDE0DQogICAgICAgIGZpZ19oZWlnaHQgOiAxMA0KICAgICAgICBmaWdfcmV0aW5hIDogMg0KICAgICAgICB0aGVtZToNCiAgICAgICAgICAgIGJvb3Rzd2F0Y2g6IGRlZmF1bHQgICAgICAgICMgY2VydWxlYW4gam91cm5hbCBmbGF0bHkgcmVhZGFibGUgcGFwZXIgc2FuZHN0b25lIC4uLg0KICAgICAgICBkZl9wcmludDogICAgZGVmYXVsdCAgICAgICAgIyBwYWdlZCBrYWJsZSB0aWJibGUgZGVmYXVsdA0KICAgICAgICBudW1iZXJfc2VjdGlvbnM6IHllcyAgICAgICAgIyBBdXRvbWF0aWMgbnVtYmVyaW5nIG9mIHNlY3Rpb25zOiB5ZXMgbm8NCiAgICAgICAgYW5jaG9yX3NlY3Rpb25zIDogVFJVRQ0KICAgICAgICBzZWN0aW9uX2RpdnMgOiBUUlVFICAgICAjIFdyYXAgc2VjdGlvbnMgaW4gPGRpdj4gdGFncywgYW5kIGF0dGFjaCBpZGVudGlmaWVycyB0byB0aGUgZW5jbG9zaW5nIDxkaXY+IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJhdGhlciB0aGFuIHRoZSBoZWFkZXIgaXRzZWxmLg0KICAgICAgICBkZXYgOiAic3ZnIiAgICAgICAgICAgICAgICAjIEdyYXBoaWNzIGRldmljZSB0byB1c2UgZm9yIGZpZ3VyZSBvdXRwdXQgKGRlZmF1bHRzIHRvIHBuZykNCiAgICAgICAgc2VsZl9jb250YWluZWQgOiBUUlVFDQogICAgICAgIGV4dHJhX2RlcGVuZGVuY2llcyA6IE5VTEwgICAgIyBFeHRyYSBkZXBlbmRlbmNpZXMgYXMgYSBsaXN0IG9mIHRoZSBodG1sX2RlcGVuZGVuY3kgY2xhc3Mgb2JqZWN0cyB0eXBpY2FsbHkgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBnZW5lcmF0ZWQgYnkgaHRtbHRvb2xzOmh0bWxEZXBlbmRlbmN5KCkuDQogICAgICAgIGNzcyA6IHN0eWxlLmNzcyAgICAgDQogICAgICAgIGluY2x1ZGVzIDogTlVMTCAgICAgICAgIyBOYW1lZCBsaXN0IG9mIGFkZGl0aW9uYWwgY29udGVudCB0byBpbmNsdWRlIHdpdGhpbiB0aGUgZG9jdW1lbnQgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgKHR5cGljYWxseSBjcmVhdGVkIHVzaW5nIHRoZSBpbmNsdWRlcyBmdW5jdGlvbikNCiAgICAgICAga2VlcF9tZCA6IEZBTFNFICAgICAgICAjIEtlZXAgdGhlIG1hcmtkb3duIGZpbGUgZ2VuZXJhdGVkIGJ5IGtuaXR0aW5nLg0KICAgICAgICBsaWJfZGlyIDogTlVMTCAgICAgICAgICAgICANCiAgICAgICAgbWRfZXh0ZW5zaW9ucyA6IE5VTEwgICAgICAgIyBNYXJrZG93biBleHRlbnNpb25zIHRvIGJlIGFkZGVkIG9yIHJlbW92ZWQgZnJvbSB0aGUgZGVmYXVsdCBkZWZpbml0aW9uIG9mIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSIE1hcmtkb3duLiBTZWUgdGhlIHJtYXJrZG93bl9mb3JtYXQgZm9yIGFkZGl0aW9uYWwgZGV0YWlscy4NCiAgICAgICAgcGFuZG9jX2FyZ3MgOiBOVUxMICAgICAgIyBBZGRpdGlvbmFsIGNvbW1hbmQgbGluZSBvcHRpb25zIHRvIHBhc3MgdG8gcGFuZG9jDQogICAgICAgIHRlbXBsYXRlIDogImRlZmF1bHQiICAgICAgIA0KICAgICAgICBtYXRoX21ldGhvZCA6ICJkZWZhdWx0IiAgICAgDQogICAgICAgIG1hdGhqYXggOiAiZGVmYXVsdCIgICAgICAgIA0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQ0KLS0tDQoNCmBgYHtyIGNodW5rIG9wdGlvbnMsIGVjaG89Rn0NCiMgQ2h1bmsgb3B0aW9ucw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBlY2hvICAgICAgID0gRiwgICAgIyBTaG91bGQgYmxvY2tzIHdpdGggcHJvZ3JhbSBjb2RlIGJlIHNob3duIGluIGtuaXR0ZWQgZG9jdW1lbnRzPw0KICBldmFsICAgICAgID0gVFJVRSwgICAgIyBTaG91bGQgcHJvZ3JhbSBjb2RlIGJlIGV2YWx1YXRlZD8NCiAgZmlnLmhlaWdodCA9IDYsICAgICAgICMgRGVmYXVsdCBoZWlnaHQgZm9yIHBsb3RzLg0KICBmaWcud2lkdGggID0gMTAsICAgICAgICMgRGVmYXVsdCB3aWR0aCBmb3IgcGxvdHMuDQogIGZpZy5hbGlnbiAgPSAiY2VudGVyIiwgIyBEZWZhdWx0IGFsaWdubWVudCBmb3IgcGxvdHMgaW4ga25pdHRlZCBkb2N1bWVudHMuDQogIHdhcm5pbmcgPSBGLA0KICB0aWR5ID0gVCwNCiAgZmlnLmNhcCA9ICIgIg0KKQ0KDQpgYGANCg0KYGBge3IgbGlicmFyaWVzIGFuZCBkYXRhIGxvYWRpbmcsIGluY2x1ZGUgPSBGfQ0KDQojIExJQlJBUklFUyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpsaWJyYXJ5KGNvbmZsaWN0ZWQpICAgICMgR2V0IGEgd2FybmluZy9lcnJvciBpZiBzZXZlcmFsIGZ1bmN0aW9ucyB3aXRoIHRoZSBzYW1lIG5hbWUgZXhpc3QuDQpsaWJyYXJ5KG1hZ3JpdHRyKSAgICAgICMgT3BlcmF0b3IgJT4lIGFuZCBhZGRpdGlvbmFsIHBpcGUtZnJpZW5kbHkgZnVuY3Rpb25zLg0KbGlicmFyeSh0aWR5dmVyc2UpICAgICAjIFRoZSBtYWluICJ0aWR5dmVyc2UiIHBhY2thZ2VzLg0KbGlicmFyeShvcGVueGxzeCkgICAgICAjIFdyaXRlIGRhdGEgdG8gRXhjZWwgZmlsZXMuDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KHBzeWNoKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkocGFuZGVyKQ0KbGlicmFyeShEVCkNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkoZm1ja2FnZSkNCg0KY29uZmxpY3RlZDo6Y29uZmxpY3RzX3ByZWZlcihkcGx5cjo6ZmlsdGVyKQ0KDQojIERBVEEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpwb3N0ID0gcmVhZC54bHN4KCJDb3BpZSBkZSByZXN1bHRhdHMgUTIgY29waWUueGxzeCIsIHNoZWV0ID0gMSkNCnByZSA9IHJlYWQueGxzeCgiQ29waWUgZGUgcmVzdWx0YXRzIFExIGNvcGllLnhsc3giLCBzaGVldCA9IDEpDQpgYGANCg0KYGBge3IgZGF0YSBtYW5hZ2VtZW50LCBpbmNsdWRlID0gRn0NCiMgQ29sbmFtZXMoKSB0byBsb3dlcmNhc2UNCmNvbG5hbWVzKHByZSkgPSB0b2xvd2VyKGNvbG5hbWVzKHByZSkpDQpjb2xuYW1lcyhwb3N0KSA9IHRvbG93ZXIoY29sbmFtZXMocG9zdCkpDQoNCiMgTUVSR0lORyBQUkUgRSBQT1NUIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnByZSA9IHByZSAlPiUgDQogICAgc2VsZWN0KC1jb250YWlucyhjKCJpZCIsInN1Ym1pdGRhdGUiLCJsYXN0cGFnZSIsInN0YXJ0bGFuZ3VhZ2UiKSkpICU+JSANCiAgICByZW5hbWUoImZpbGllcmUiPWIxLCAiaWQiID0gYTEpICU+JSANCiAgICBtdXRhdGUodGVzdCA9ICJwcmUiKSAlPiUgDQogICAgbXV0YXRlKGFjcm9zcyhzMXExOnM3cTIsIGFzLm51bWVyaWMpKSAlPiUgDQogICAgbXV0YXRlKGZpbGllcmUgPSBjYXNlX3doZW4oZmlsaWVyZSA9PSAiw6l0dWRpYW50KGUpIGVuIG1hw69ldXRpcXVlIiB+ICJtYWlldXRpcXVlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxpZXJlID09ICLDqXR1ZGlhbnQoZSkgZW4gb3J0aG9waG9uaWUiIH4gIm9ydGhvcGhvbmllIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxpZXJlID09ICLDqXR1ZGlhbnQoZSkgZW4gcGhhcm1hY2llIiB+ICJwaGFybWFjaWUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGllcmUgPT0gIsOpdHVkaWFudChlKSBJREUiIH4gIklERSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsaWVyZSA9PSAiw6l0dWRpYW50KGUpIE1LRSIgfiAiTUtFIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxpZXJlID09ICJpbnRlcm5lIGRlIG3DqWRlY2luZSBnw6luw6lyYWxlIiB+ICJtZWRlY2luZSBnZW5lcmFsZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgICAgICAgICkNCg0KcG9zdCA9IHBvc3QgJT4lDQogICAgZmlsdGVyKCFpcy5uYShzdWJtaXRkYXRlKSkgJT4lIA0KICAgIHNlbGVjdCgtY29udGFpbnMoYygiaWQiLCJzdWJtaXRkYXRlIiwibGFzdHBhZ2UiLCJzdGFydGxhbmd1YWdlIiwieDI2IiwieDI3IikpKSAlPiUgDQogICAgcmVuYW1lKCJpZCIgPSBhMSkgJT4lIA0KICAgIGxlZnRfam9pbihwcmVbLGMoImlkIiwiZmlsaWVyZSIpXSwgYnkgPSAiaWQiKSAlPiUgDQogICAgcmVsb2NhdGUoZmlsaWVyZSwgLmFmdGVyID0gImlkIikgJT4lIA0KICAgIG11dGF0ZSh0ZXN0ID0gInBvc3QiKSAlPiUgDQogICAgbXV0YXRlKGFjcm9zcyhzMXExOnM3cTIsIGFzLm51bWVyaWMpKQ0KDQojIE1lcmdpbmcNCmRhdGEgPSByYmluZChwcmUscG9zdCkgJT4lIHRpYmJsZQ0KDQojIERBVEEgTUFOQUdFTUVOVCBtZXJnZWQgREYgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZGF0YSA9IGRhdGEgJT4lIA0KICAgIG11dGF0ZShhY3Jvc3MoczFxMTpzN3EyLCBhcy5udW1lcmljKSkgJT4lIA0KICAgIGRpc3RpbmN0KCkgJT4lIA0KICAgIHJlbG9jYXRlKHRlc3QsIC5hZnRlciA9ICJpZCIpDQoNCiMgQWRkaW5nIG1lYW4gc2NvcmUgY29sdW1uDQpkYXRhID0gZGF0YSAlPiUgbXV0YXRlKHNjb3JlID0gcm91bmQocm93TWVhbnMoYWNyb3NzKHMxcTE6czdxMiksbmEucm09VCksMikpDQoNCiMgQ29tcHV0aW5nIG1pc3NpbmcgdmFsdWVzIHBlciByb3cNCmRhdGEgPSBkYXRhICU+JSBmaWx0ZXIoIWlzLm5hKGlkKSkgJT4lIA0KICAgIG11dGF0ZShuYV9jb3VudHMgPSByb3dTdW1zKGFjcm9zcyhzMXExOnM3cTIsIGlzLm5hKSkpDQpgYGANCg0KIyBUb3VzIGxlcyBxdWVzdGlvbm5haXJlcyB7LnRhYnNldH0NCg0KIyMgRXhwbG9yYXRpb24gZHUgZGF0YWJhc2UNCg0KYGBge3IgZmlsdGVyaW5nIG91dCBpbnZpZGFsaWQgcXVlc3Rpb25uYWlyZXMsIGluY2x1ZGUgPSBGfQ0Kcm93c18xID0gbnJvdyhkYXRhKQ0KdW5pcXVlX2lkc18xID0gbl9kaXN0aW5jdChkYXRhJGlkKQ0KDQojIFJlbW92aW5nIG1pc3NpbmcgSURzIHJvd3MgKG49NCkNCmRhdGEgPSBkYXRhICU+JSBmaWx0ZXIoIWlzLm5hKGlkKSkNCnVuaXF1ZV9pZHNfMiA9IG5fZGlzdGluY3QoZGF0YSRpZCkNCnJvd3NfMiA9IG5yb3coZGF0YSkNCg0KIyBFbXB0eSBxdWVzdGlvbm5haXJlcw0KZW1wdHlfcSA9IHN1bShkYXRhJG5hX2NvdW50cz09MjApDQoNCg0KIyBSZW1vdmluZyB0b3RhbGx5IGluY29tcGxldGUgcXVlc3Rpb25uYWlyZXMNCmRhdGEgPSBkYXRhICU+JSBmaWx0ZXIobmFfY291bnRzPDIwKQ0KdW5pcXVlX2lkc18zID0gbl9kaXN0aW5jdChkYXRhJGlkKQ0Kcm93c18zID0gbnJvdyhkYXRhKQ0KDQpgYGANCg0KU2FjaGFudCBsZXMgcHJvYmzDqG1lcyBxdSdvbiBhIGF2ZWMgbCdJRCB1bmlxdWUsIHBvdXIgbCdhbmFseXNlIHN0YXQgb24gc2VyYSBvYmxpZ8OpIGQnZXhjbHVyZSB0b3VzIGxlcyBJRHMgbm9uIHVuaXF1ZS4gTWFsaGV1cmV1c2VtZW50IGxhIHZhcmlhYmxlIGZpbGnDqHJlIHBvdXIgbGUgInRlc3QgMiIgZXN0IGltcG9zc2libGUgw6AgcmVjb25zdHJ1aXJlIHNhbnMgY3LDqWVyIGRlcyBkb3VibG9ucyBkb25jIGMnZXN0IGxlIHNldWwgY2hvaXggcXUnb24gYSBwb3VyIGwnYW5hbHlzZS4gTWFpcyB2b3lvbnMgcXVhbmQgbcOqbWUgY2VsdWkgcXVpIMOpdGFpdCBub3RyZSBwb2ludCBkZSBkw6lwYXJ0Lg0KDQpBIGNlIHBvaW50IGzDoCBvbiBhIGByIHJvd3NfMWAgcXVlc2l0b25uYWlyZXMgbWFpcyBub3VzIG4nYXZvbnMgcGFzIHVuZSBpZMOpZSBwcsOpY2lzZSBkZSBjb21iaWVuIGRlIHN1amV0cyB1bmlxdWVzIG9uIHBldXQgw6p0cmUgY2VydGFpbnMgZCdhdm9pci4gQWN0dWFsbGVtZW50IGEgYHIgdW5pcXVlX2lkc18xYCBJRHMgZGlmZmVyZW50cyBtYWlzIGR1IGNvdXAgb24gYSBgciByb3dzXzEtKHVuaXF1ZV9pZHNfMSoyKWAgZG91YmxvbnMuDQoNCmByIGVtcHR5X3FgIG9uIHBldXQgbGVzIGV4Y2x1cmUgcGFyY2UgcXVlIGlscyBzb250IHZpZGVzIGV0IDQgcGFyY2UgcXVlIGwnSUQgZXN0IG1hbnF1YW50LCBwb3VyIGFycml2ZXIgw6AgYHIgcm93c18zYCBxdWVzdGlvbm5haXJlcyBldCBgciB1bmlxdWVfaWRzXzNgIElEcy4gTWV0dG9ucyBtYWludGVuYW50IGxlcyBkb3VibG9ucyBlbiDDqXZpZGVuY2UuDQoNCmBgYHtyIElEcyB3aXRoIHRvbyBtYW55IGVudHJpZXN9DQpkYXRhICU+JSANCiAgICBncm91cF9ieShpZCkgJT4lIA0KICAgIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogICAgYXJyYW5nZShkZXNjKG4pKSAlPiUNCiAgICBkYXRhdGFibGUob3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjZG9tID0gJ3QnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9ICJhdXRvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9IFQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkNCg0KcHJvYmxlbWF0aWNfSURzID0gZGF0YSAlPiUgZ3JvdXBfYnkoaWQpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JSBmaWx0ZXIobj4yKSAlPiUgbnJvdw0KDQpgYGANCg0KQ29tbWUgdHUgcGV1eCBsZSB2b2lyIG9uIHNlbWJsZSBhdm9pciBgciBwcm9ibGVtYXRpY19JRHNgIElEcyBwcmVzZW50cyAqKmF1IG1vaW5zKiogMyBmb2lzLiBDcmV1c29ucyBwbHVzIGxvaW4gcG91ciB2b2lyIHNpIG9uIGlkZW50aWZpZSB1biBncm91cGUgZCdJRHMgcHJvYmxlbWF0aXF1ZS4gVGjDqW9yaXF1ZW1lbnQsIHNpIGxlcyBnZW5zIGF2YWllbnQgcmVzcGVjdMOpIGxlcyByw6lnbGVzIHBvdXIgbGEgY3LDqWF0aW9uIGRlIGwnaWRlbnRpZmlhbnQgYW5vbnltZSwgbCdpZGVudGlmaWFudCBkZXZyYWl0IHN1aXZyZSBsZSAqcGF0dGVybiogc3VpdmFudDogMSBjaGlmZnJlIC0gMiBsZXR0cmVzIC0gMiBjaGlmZnJlcy4NCg0KVm95b25zIHBvdXIgY29tYmllbiBkZSBsaWduZXMgY2UgKnBhdHRlcm4qIGVzdCByZXNwZWN0w6k6DQoNCmBgYHtyIGxvb2tpbmcgZm9yIElEcyBub3QgZm9sbG93aW5nIHRoZSBydWxlc30NCnN0cl9kZXRlY3QoZGF0YSRpZCwgIls6ZGlnaXQ6XXsxfVs6YWxwaGE6XXsyfVs6ZGlnaXQ6XXsyfSIpICU+JSANCiAgICB0YWJsZSAlPiUNCiAgICBwYW5kZXIoKQ0KYGBgDQoNCkNlbGEgbm91cyBkaXQgcXVlICoqbcOqbWUgc2kqKiBvbiByZWdhcmRlIHNldWxlbWVudCBsZXMgZ2VucyBxdWkgb250IHJlc3BlY3TDqSBsYSBwcm9jZWR1cmUgcG91ciBsYSBjcsOpYXRpb24gZGVzIElEcywgb24gw6AgdGpycyBkZXMgbGlnbmVzIGRlIHRyb3AuIEQnYWJvcmQsIHJlZ2FyZG9ucyBsZXMgZW50csOpcyBkZXMgZ2VucyBxdWkgb250IHRhcMOpIHVuIElEIGF1IHBpZiAoZG9uYyBsZXMgImZhbHNlcyIpLg0KDQpgYGB7ciBkYXRhZnJhbWUgSURzIGFiZXJyYW50c30NCmRhdGEgJT4lIA0KICAgIGZpbHRlcighc3RyX2RldGVjdChpZCwgIls6ZGlnaXQ6XXsxfVs6YWxwaGE6XXsyfVs6ZGlnaXQ6XXsyfSIpKSAlPiUNCiAgICBhcnJhbmdlKGlkKSAlPiUgDQogICAgZGF0YXRhYmxlKG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2RvbSA9ICd0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAiYXV0byIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFggPSBUDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpDQpgYGANCg0KTsOpYW5tb2lucywgcydpbHMgb250IHV0aWxpc8OpIDIgZm9pcyAqKmxlIG3Dqm1lKiogaWRlbnRpZmlhbnQgKmFiZXJyYW50KiBvbiBwb3VycmEgcXVhbmQgbcOqbWUgbGVzIGFwcGFyaWVyLiBWb3lvbnMgZG9uYyBsZXMgSURzIHF1aSBhcHBhcmFpc3NlbnQgKipcPjIqKiBmb2lzLiBMZXMgSURzICphYmVycmFudHMqIHF1aSBhcHBhcmFpc3NlbnQgKioyKiogZm9pcyBvbiBwZXV0IGxlcyB1dGlsaXNlciwgbGVzIElEcyBxdWkgYXBwYXJhaXNzZW50IHF1J3VuZSBzZXVsZSBmb2lzLCBpZGVtLCBvbiBwZXV0IGxlcyBnYXJkZXIgcG91ciBsYSBwYXJ0aWUgZGVzY3JpcHRpdmUgKGNhcnLDqW1lbnQgaWxzIG5lIHNlcmEgcGFzIHBvc3NpYmxlIGRlIGxlcyB1dGlsaXNlciBwb3VyIGxhIGNvbXBhcmFpc29uIGF2YW50LWFwcsOocykuDQoNCmBgYHtyIElEcyBhYmVycmFudHMgcHJlc2VudGVzIDJwbHVzIGZvaXN9DQpkYXRhICU+JSANCiAgICBmaWx0ZXIoIXN0cl9kZXRlY3QoaWQsICJbOmRpZ2l0Ol17MX1bOmFscGhhOl17Mn1bOmRpZ2l0Ol17Mn0iKSkgJT4lDQogICAgZ3JvdXBfYnkoaWQpICU+JQ0KICAgIHN1bW1hcmlzZShuPW4oKSkgJT4lIA0KICAgIGFycmFuZ2UoZGVzYyhuKSkgJT4lDQogICAgZGF0YXRhYmxlKG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2RvbSA9ICd0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAiYXV0byIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFggPSBUDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpDQpgYGANCg0KT24gdm9pdCBxdWUgbGUgc2V1bCBJRCBwcm9ibGVtYXRpcXVlIHBhcm1pIGxlcyAqYWJlcnJhbnRzKiBlc3QgKioiMTIzNDUiKiouIFZveW9ucyBsZXMgbGlnbmVzIHF1aSBjb3JyZXNwb25kZW50IMOgIGNldCBJRC4NCg0KYGBge3IgZmlsdGVyaW5nIG9uIElEIDEyMzQ1fQ0KZGF0YSAlPiUgDQogICAgZmlsdGVyKGlkPT0iMTIzNDUiKSAlPiUNCiAgICBkYXRhdGFibGUob3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjZG9tID0gJ3QnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9ICJhdXRvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9IFQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkNCmBgYA0KDQpPbiBzZW1ibGUgYXZvaXIgMSBJREUgZXQgMSBNRywgcXVpIG9udCB1biBkb3VibG9uIGRlICIyw6htZSB0ZXN0Ii4gU2kgb24gcmVnYXJkZSBhdmVjIGF0dGVudGlvbiBsYSBsaWduZSAzIGV0IDQgc29udCBpZGVudGlxdWVzLCBhdmVjIHVuZSAiZmlsacOocmUiIGRpZmbDqXJlbnRlLiBTaSBsYSBsaWduZSAzIGV0IDQgw6l0YWllbnQgcGFyIGV4ZW1wbGUgIklERSIgZXQgbGEgbGlnbmUgNSBldCA2IMOpdGFpZW50ICJtZWRlY2luZSBnZW5lcmFsZSIgb24gYXVyYWl0IGlkZW50aWZpw6kgZGVzIGRvdWJsb25zIC0tXD4gcHJvYmzDqG1lIHLDqXNvbHUuIE1haXMgZGFucyBjZSBjYXMgb24gYSBkZXMgZG91YmxvbnMgKipFVCoqIDIgcGVyc29ubmVzIHF1aSBvbnQgcmVudHLDqSAyIGZvaXMgbGUgIjLDqG1lIHRlc3QiIGVuIGNoYW5nZWFudCBhdXNzaSBkZSBmaWxpw6hyZS4gSWwgZXN0IGRvbmMgaW1wb3NzaWJsZSBkZSByYXR0YWNoZXIgY2VzIHF1ZXN0aW9ubmFpcmVzIMOgIHVuICJ0ZXN0IDEiLiBDZSBxdWkgZXN0IHRyw6hzIHRyw6hzIGJpemFycmUsIGVzdCBxdWUgbGVzIGxpZ25lcyAzIGV0IDUgc29udCBJREVOVElRVUVTIGF1eCBsaWduZXMgNCBldCA2LiBDZSBxdSdvbiBwZXV0IGZhaXJlLCBlc3QgcHJlbmRyZSBsYSBtb3llbm5lIGRlcyBsaWduZXMgMy01IGV0IDQtNi4gTGUgbcOqbWUgYXBwcm9jaGUgbm91cyBzZXJhIHV0aWxlIHBvdXIgZ8OpcmVyIGxlcyBJRHMgKm5vbiBhYmVycmFudHMqIGRvdWJsb25zIHF1aSBzb250IGxlcyBzdWl2YW50czoNCg0KQSBjZSBwb2ludCwgYXZhbnQgZGUgcGFzc2VyIMOgIHJlZ2FyZGVyIGwnZW5zZW1ibGUgZGVzIHRlc3RzIGFwcGFyacOpcywgb24gcGV1dCBxdWFuZCBtZW1lIGpldHRlciB1biBjb3VwIGQnxZNpbCDDoCAidGVzdCAxIiBldCAidGVzdCAyIiBzw6lwYXLDqW1lbnQgcG91ciB2b2lyIGNvbW1lbnQgbGVzIHNjb3JlIHNvbnQgZGlzdHJpYnXDqXMuDQoNCiMjIERvbm7DqWVzIG1hbnF1YW50ZXMNCg0KYGBge3IgYWxsIHRlc3RzIE5Bc30NCmRhdGEgJT4lIA0KICBncm91cF9ieSh0ZXN0KSAlPiUNCiAgY291bnQobmFfY291bnRzKSAlPiUgDQogIG11dGF0ZSgiJSIgPSByb3VuZChhcy5udW1lcmljKG4vc3VtKG4pKjEwMCksIDIpKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdCgtdGVzdCkgJT4lIA0KICByZW5hbWUoIk5iIG1pc3NpbmcgdmFsdWVzIiA9IG5hX2NvdW50cywgZnJlcXVlbmN5ID0gbikgJT4lIA0KICBrYWJsZShjYXB0aW9uID0gIioqTmIgZGUgdmFsZXVycyBtYW5xdWFudGVzIHBhciBxdWVzdGlvbm5haXJlKioiKSAlPiUgDQogIGthYmxlX3BhcGVyKCkgJT4lIA0KICBwYWNrX3Jvd3MoaW5kZXggPSBjKCJQb3N0Ij02LCJQcmUiPTcpKQ0KYGBgDQoNCiMjIERpc3RyaWJ1dGlvbiAiZmlsacOocmUiICgxZXIgZmljaGllcikNCg0KYGBge3IgMXN0IHRlc3QgZGlzdHJpYnV0aW9uIGZpbGllcmV9DQpnID0gcHJlICU+JSANCiAgICBnZ3Bsb3QoYWVzKHg9ZmlsaWVyZSkpKw0KICAgIGdlb21fYmFyKCkrDQogICAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gcGFyIGZpbGnDqHJlIGF1IG1vbWVudCBkdSAxZXIgdGVzdCIpKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTAwMCwgMTApKSsNCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpDQoNCmdncGxvdGx5KCkNCmBgYA0KDQojIyBEaXN0cmlidXRpb24gc2NvcmUgbW95ZW4gZHUgcXVlc3Rpb25uYWlyZQ0KDQpgYGB7ciBhbGwgdGVzdHMgZGlzcGVyc2lvbm1lYXN1cmVzfQ0KICAgICMgZGVzY3JpYmUgdGFibGVzDQpyYmluZChkZXNjcmliZShkYXRhJHNjb3JlLCBmYXN0ID0gVCksDQogICAgICBkZXNjcmliZShkYXRhJHNjb3JlW2RhdGEkdGVzdD09InByZSJdLCBmYXN0ID0gVCksDQogICAgICBkZXNjcmliZShkYXRhJHNjb3JlW2RhdGEkdGVzdD09InBvc3QiXSwgZmFzdCA9IFQpKSAlPiUgDQogICAgYXMuZGF0YS5mcmFtZShyb3cubmFtZXMgPSBjKCJFbnNlbWJsZSIsICJwcmUiLCAicG9zdCIpKSAlPiUNCiAgICByZW5hbWUoZGV2aWF0aW9uX3N0YW5kYXJkID0gc2QsIGVjYXJ0X3R5cGUgPSBzZSkgJT4lIA0KICAgIGthYmxlKGNhcHRpb24gPSAiKipTY29yZSAtIFRvdXMgdGVzdHMgY29uZm9uZHVzIC0gTWVzdXJlcyBkZSBkaXNwZXJzaW9uKioiLGRpZ2l0cyA9IDMpICU+JQ0KICAgIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IFQpICU+JSANCiAga2FibGVfcGFwZXIoKQ0KDQogICAgIyBpZGVtIGJ5IGZpbGnDqHJlDQpwcmUgJT4lDQogICAgbXV0YXRlKHNjb3JlID0gcm91bmQocm93TWVhbnMoYWNyb3NzKHMxcTE6czdxMiksbmEucm09VCksMikpICU+JSANCiAgICBncm91cF9ieShmaWxpZXJlKSAlPiUgc3VtbWFyaXNlKGRlc2NyaWJlKHNjb3JlLGZhc3Q9VCkpICU+JSANCiAgICBhcy5kYXRhLmZyYW1lKHJvdy5uYW1lcyA9IGMoIkVuc2VtYmxlIiwgInByZSIsICJwb3N0IikpICU+JQ0KICAgIHJlbmFtZShkZXZpYXRpb25fc3RhbmRhcmQgPSBzZCwgZWNhcnRfdHlwZSA9IHNlKSAlPiUgDQogICAga2FibGUoY2FwdGlvbiA9ICIqKnNjb3JlIC0gMWVyIHRlc3QgLSBNZXN1cmVzIGRlIGRpc3BlcnNpb24gYnkgZmlsacOocmUqKiIsZGlnaXRzID0gMyklPiUNCiAgICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBUKSAlPiUgDQogIGthYmxlX3BhcGVyKCkNCmBgYA0KDQpgYGB7ciAxc3QgdGVzdCBzY29yZSBoaXN0b2dyYW1tZX0NCmcgPSBkYXRhICU+JSANCiAjIHBpdm90X2xvbmdlcihjb2xzID0gYygicG9zdCIsICJwcmUiKSwgbmFtZXNfdG8gPSAidGVzdCIsIHZhbHVlc190byA9ICJzY29yZSIpICU+JQ0KICBtdXRhdGUoc2NvcmUgPSByb3VuZChzY29yZSwgMikpICU+JQ0KICBtdXRhdGUoc2NvcmUgPSBmYWN0b3Ioc2NvcmUsIGxldmVscyA9IHJldihzb3J0KHVuaXF1ZShzY29yZSkpKSkpICU+JQ0KICBtdXRhdGUoc2NvcmUgPSBjdXQoYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoc2NvcmUpKSwgYnJlYWtzID0gc2VxKDEsNywwLjUpKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IHNjb3JlKSkgKw0KICBnZW9tX2JhcihhZXMoZmlsbCA9IHRlc3QpLCBhbHBoYSA9IDAuMywgcG9zaXRpb24gPSAiaWRlbnRpdHkiKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTAwMCwgMTApKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIHNjb3JlIG1veWVuIikrDQogIHRoZW1lKHRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKQ0KDQpnZ3Bsb3RseSgpDQoNCmBgYA0KDQojIElEIHVuaXF1ZXMgey50YWJzZXR9DQoNClByZW5vbnMgbWFpbnRlbmFudCBsYSBwb3B1bGF0aW9uIGNvbXBvc8OpZSBzZXVsZW1lbnQgcGFyIGRlcyBJRHMgdW5pcXVlcyAocXVpIGFwcGFyYWlzc2VudCBhdSBtYXggMSBmb2lzIHBhciB0ZXN0KS4NCg0KYGBge3IgcHJlcGFyaW5nIGRhdGEgaWQgdW5pcXVlc30NCnBvc3QgPSByZWFkLnhsc3goIkNvcGllIGRlIHJlc3VsdGF0cyBRMiBjb3BpZS54bHN4Iiwgc2hlZXQgPSAxKQ0KcHJlID0gcmVhZC54bHN4KCJDb3BpZSBkZSByZXN1bHRhdHMgUTEgY29waWUueGxzeCIsIHNoZWV0ID0gMSkNCg0KY29sbmFtZXMocHJlKSA9IHRvbG93ZXIoY29sbmFtZXMocHJlKSkNCmNvbG5hbWVzKHBvc3QpID0gdG9sb3dlcihjb2xuYW1lcyhwb3N0KSkNCg0KIyBjbGVhbmluZyBhbmQgcHJlcGFyaW5nICJwcmUiIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnByZSA9IHByZSAlPiUgDQogICAgc2VsZWN0KC1jb250YWlucyhjKCJpZCIsInN1Ym1pdGRhdGUiLCJsYXN0cGFnZSIsInN0YXJ0bGFuZ3VhZ2UiKSkpICU+JSANCiAgICByZW5hbWUoImZpbGllcmUiPWIxLCAiaWQiID0gYTEpICU+JSANCiAgICBtdXRhdGUodGVzdCA9ICJwcmUiKSAlPiUgDQogICAgbXV0YXRlKGFjcm9zcyhzMXExOnM3cTIsIGFzLm51bWVyaWMpKSAlPiUgDQogICAgbXV0YXRlKGZpbGllcmUgPSBjYXNlX3doZW4oZmlsaWVyZSA9PSAiw6l0dWRpYW50KGUpIGVuIG1hw69ldXRpcXVlIiB+ICJtYWlldXRpcXVlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxpZXJlID09ICLDqXR1ZGlhbnQoZSkgZW4gb3J0aG9waG9uaWUiIH4gIm9ydGhvcGhvbmllIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxpZXJlID09ICLDqXR1ZGlhbnQoZSkgZW4gcGhhcm1hY2llIiB+ICJwaGFybWFjaWUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGllcmUgPT0gIsOpdHVkaWFudChlKSBJREUiIH4gIklERSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsaWVyZSA9PSAiw6l0dWRpYW50KGUpIE1LRSIgfiAiTUtFIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxpZXJlID09ICJpbnRlcm5lIGRlIG3DqWRlY2luZSBnw6luw6lyYWxlIiB+ICJtZWRlY2luZSBnZW5lcmFsZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgICAgICAgICkNCg0KIyBjbGVhbmluZyBhbmQgcHJlcGFyaW5nICJwb3N0IiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpwb3N0ID0gcG9zdCAlPiUNCiAgICBmaWx0ZXIoIWlzLm5hKHN1Ym1pdGRhdGUpKSAlPiUgDQogICAgc2VsZWN0KC1jb250YWlucyhjKCJpZCIsInN1Ym1pdGRhdGUiLCJsYXN0cGFnZSIsInN0YXJ0bGFuZ3VhZ2UiLCJ4MjYiLCJ4MjciKSkpICU+JSANCiAgICByZW5hbWUoImlkIiA9IGExKSAlPiUgDQogICAgbGVmdF9qb2luKHByZVssYygiaWQiLCJmaWxpZXJlIildLCBieSA9ICJpZCIpICU+JSANCiAgICByZWxvY2F0ZShmaWxpZXJlLCAuYWZ0ZXIgPSAiaWQiKSAlPiUgDQogICAgbXV0YXRlKHRlc3QgPSAicG9zdCIpICU+JSANCiAgICBtdXRhdGUoYWNyb3NzKHMxcTE6czdxMiwgYXMubnVtZXJpYykpDQoNCiMgZXhjbHVkaW5nIElEcyBhcHBlYXJpbmcgbW9yZSB0aGFuIDEgdGltZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnByZV9pbmRleCA9IHByZSAlPiUgZ3JvdXBfYnkoaWQpICU+JSBjb3VudCAlPiUgZmlsdGVyKG49PTEpICU+JSBwdWxsKGlkKQ0KcG9zdF9pbmRleCA9IHBvc3QgJT4lIGdyb3VwX2J5KGlkKSAlPiUgY291bnQgJT4lIGZpbHRlcihuPT0xKSAlPiUgcHVsbChpZCkNCg0KcHJlID0gcHJlICU+JSBmaWx0ZXIoaWQgJWluJSBwcmVfaW5kZXgpDQpwb3N0ID0gcG9zdCAlPiUgZmlsdGVyKGlkICVpbiUgcG9zdF9pbmRleCkNCg0KIyBtZXJnZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZGF0YSA9IHJiaW5kKHByZSwgcG9zdCkgJT4lIA0KICAgIG11dGF0ZShuYV9jb3VudHMgPSByb3dTdW1zKGFjcm9zcyhzMXExOnM3cTIsIGlzLm5hKSkpICU+JSANCiAgICBmaWx0ZXIobmFfY291bnRzPDIwKSAlPiUgDQogICAgbXV0YXRlKHNjb3JlID0gcm91bmQocm93TWVhbnMoYWNyb3NzKHMxcTE6czdxMiksbmEucm09VCksMikpDQpgYGANCg0KIyMgUG9wdWxhdGlvbiBldCBkaXN0cmlidXRpb24gcGFyIGZpbGnDqHJlDQoNCk5vdXMgYXZvbnMgdW4gdG90YWwgZGUgYHIgbl9kaXN0aW5jdChkYXRhJGlkKWAgc3VqZXRzLCByZXBhcnRpcyBkZSBsYSBmYcOnb24gc3VpdmFudGUuIEF0dGVudGlvbiwgY2V1eCBuZSBzb250IHBhcyBlbmNvcmUgbGVzIHN1amV0cyBxdWkgb250IGZhaXQgbGVzIDIgdGVzdHMsIGNldXggY2kgc29udCB0b3VzIGxlcyBJRHMgcXVpIGFwcGFyYWlzc2VudCBhdSBtYXggMSBmb2lzIHBhciB0ZXN0Lg0KDQpgYGB7ciBpZCB1bmlxdWVzIGRpc3RyaWJ1dGlvbiBwYXIgZmlsaWVyZX0NCmRhdGEgJT4lIA0KICBkaXN0aW5jdChpZCxmaWxpZXJlKSAlJCUgDQogICAgdGFibGUoZmlsaWVyZSx1c2VOQSA9ICJpZmFueSIpICU+JSANCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICAgIG11dGF0ZSgiJSIgPSByb3VuZChGcmVxL3N1bShGcmVxKSoxMDAsIDMpKSAlPiUgDQogICAgcmVuYW1lKCJOYiBzdWpldCBwYXJ0aWNpcGFudHMiID0gRnJlcSkgJT4lIA0KICAgIGFkb3JuX3RvdGFscygpICU+JSANCiAgICBrYWJsZShjYXB0aW9uID0gIjxiPlJlcGFydGl0aW9uIHN1amV0cyBwYXIgZmlsacOocmU8Yj4iLCBkaWdpdD0yKSAlPiUgDQogIGthYmxlX3BhcGVyKCkNCg0KYGBgDQoNCmBgYHtyIGlkIHVuaXF1ZXMgaGlzdG9ncmFtbWUgZmlsaWVyZX0NCmcgPSBkYXRhICU+JSANCiAgICBnZ3Bsb3QoYWVzKHg9ZmlsaWVyZSkpKw0KICAgIGdlb21fYmFyKCkrDQogICAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gcGFyIGZpbGnDqHJlIElEcyB1bmlxdWVzIikrDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxMDAwLCAxMCkpKw0KICBzY2FsZV94X2Rpc2NyZXRlKG5hLnRyYW5zbGF0ZT1UKSsNCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpDQoNCmdncGxvdGx5KCkNCmBgYA0KDQpMYSBkaWZmw6lyZW5jZSBwYXIgcmFwcG9ydCDDoCBsYSBkaXN0cmlidXRpb24gcHLDqWPDqWRlbnRlIGVzdCBwcmVzcXVlIGludmlzaWJsZSwgY2UgcXVpIGVzdCBiaWVuLiBOb3VzIG5lIHNvbW1lcyBwYXMgZW4gdHJhaW4gZCdpbnRyb2R1aXJlIGRlcyBiaWFpcyBjb21tZSBpbnZvbG9udGFpcmVtZW50IHPDqWxlY3Rpb25uZXIgdW5lIHNvdXMtcG9wdWxhdGlvbiBzcMOpY2lmaXF1ZS4gVm95b25zIG1haW50ZW5hbnQgcXVpIHNvbnQgbGVzIDggc3VqZXRzIHNhbnMgZmlsacOocmU6DQoNCmBgYHtyfQ0KeCA9IGRhdGEgJT4lIGZpbHRlcihpcy5uYShmaWxpZXJlKSkgICU+JSBwdWxsKGlkKQ0KDQpkYXRhICU+JSANCiAgICBmaWx0ZXIoaWQgJWluJSB4KSAlPiUgDQogICAgcmVsb2NhdGUodGVzdCwgLmFmdGVyPWlkKSAlPiUgDQogICAgZGF0YXRhYmxlKG9wdGlvbnMgPSBsaXN0KA0KICAgICAgcGFnZUxlbmd0aCA9IDEwLA0KICAgICAgc2Nyb2xsWCA9IFRSVUUNCiAgKSkNCmBgYA0KDQpBcHBhcsOpbW1lbnQgY2Ugc29udCBkZXMgZ2VucyBxdWkgb250IGZhaXQgc2V1bGVtZW50IGxlIDLDqG1lIHRlc3QuDQoNCiMjIERvbm7DqWVzIG1hbnF1YW50ZXMNCg0KVm95b25zIHN1ciB0b3V0IGwnZW5zZW1ibGUgZGUgdGVzdHMsIGNvbWJpZW4gZGUgZG9ubsOpZXMgbWFucXVhbnRlcyBvbiBhLiBDZSBzb250IGRlcyAidnJhaWVzIiBkb25uw6llcyBtYW5xdWFudGVzICoqT1UqKiBkZXMgIk5TUCIgcXVpIG4nw6l0YWl0IHBhcyBwZXJ0aW5lbnRzIHBvdXIgbGEgcXVlc3Rpb24gZXQgdnJhaXNlbWJsYWJsZW1lbnQgcHJpcyBwb3VyIGRlcyAqIk5lIHNhaXQgcGFzIi4qDQoNCmBgYHtyfQ0KdGFibGUoZGF0YSRuYV9jb3VudHMpICU+JSANCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICAgIG11dGF0ZSgiJSIgPSByb3VuZChhcy5udW1lcmljKEZyZXEvc3VtKEZyZXEpKjEwMCksIDIpLA0KICAgICAgICAgICBWYXIxID0gcm91bmQoYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoVmFyMSkpLDIpKSAlPiUgDQogICAgcmVuYW1lKCJOYiBtaXNzaW5nIHZhbHVlcyIgPSBWYXIxKSAlPiUgDQogICAga2FibGUoY2FwdGlvbiA9ICI8Yj4gTmIgZGUgdmFsZXVycyBtYW5xdWFudGVzIHBhciBxdWVzdGlvbm5haXJlPGI+IikgJT4lIA0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBUKSAlPiUgDQogIGthYmxlX3BhcGVyKCkNCg0KYGBgDQoNCk9uIHZvaXQgcXVlIGxlcyB0ZXN0cyBzb250IGJpZW4gY29tcGxldHMgZ2xvYmFsZW1lbnQuIFNldWxlbWVudCA3IHF1ZXN0aW9ubmFpcmVzIG9udCAqKlw+PTMqKiB2YWxldXJzIG1hbnF1YW50ZXMuDQoNCiMjIERpc3RyaWJ1dGlvbiBzY29yZSBtb3llbg0KDQpgYGB7cn0NCnJiaW5kKGRlc2NyaWJlKGRhdGEkc2NvcmUsIGZhc3QgPSBUKSwNCiAgICAgIGRlc2NyaWJlKGRhdGEkc2NvcmVbZGF0YSR0ZXN0PT0icHJlIl0sIGZhc3QgPSBUKSwNCiAgICAgIGRlc2NyaWJlKGRhdGEkc2NvcmVbZGF0YSR0ZXN0PT0icG9zdCJdLCBmYXN0ID0gVCkpICU+JSANCiAgICBhcy5kYXRhLmZyYW1lKHJvdy5uYW1lcyA9IGMoIkVuc2VtYmxlIiwgInByZSIsICJwb3N0IikpICU+JQ0KICAgIHJlbmFtZShkZXZpYXRpb25fc3RhbmRhcmQgPSBzZCwgZWNhcnRfdHlwZSA9IHNlKSAlPiUgDQogICAga2FibGUoY2FwdGlvbiA9ICI8Yj5TY29yZSAtIElEIHVuaXF1ZXMgLSBNZXN1cmVzIGRlIGRpc3BlcnNpb248Yj4iLCANCiAgICAgICAgICBkaWdpdHMgPSAzKSAlPiUNCiAgICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBUKSAlPiUgDQogICAga2FibGVfcGFwZXIoKQ0KYGBgDQoNCmBgYHtyfQ0KIyBpZGVtIGJ5IGZpbGnDqHJlDQpwcmUgJT4lDQogICAgbXV0YXRlKHNjb3JlID0gcm91bmQocm93TWVhbnMoYWNyb3NzKHMxcTE6czdxMiksbmEucm09VCksMikpICU+JSANCiAgICBncm91cF9ieShmaWxpZXJlKSAlPiUgDQogICAgc3VtbWFyaXNlKGRlc2NyaWJlKHNjb3JlLGZhc3Q9VCkpICU+JSANCiAgICBhcy5kYXRhLmZyYW1lKHJvdy5uYW1lcyA9IGMoIkVuc2VtYmxlIiwgInByZSIsICJwb3N0IikpICU+JQ0KICAgIHJlbmFtZShkZXZpYXRpb25fc3RhbmRhcmQgPSBzZCwgZWNhcnRfdHlwZSA9IHNlKSAlPiUgDQogICAga2FibGUoY2FwdGlvbiA9ICI8Yj5TY29yZSAtIElEIHVuaXF1ZXMgLSBNZXN1cmVzIGRlIGRpc3BlcnNpb24gYnkgZmlsacOocmU8Yj4iLA0KICAgICAgICAgIGRpZ2l0cyA9IDMpICU+JQ0KICAgIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IFQpICU+JSANCiAgICBrYWJsZV9wYXBlcigpDQpgYGANCg0KYGBge3IgaWQgdW5pcXVlcyBzY29yZSBkaXN0cmlidXRpb259DQpnID0gZGF0YSAlPiUgDQogIyBwaXZvdF9sb25nZXIoY29scyA9IGMoInBvc3QiLCAicHJlIiksIG5hbWVzX3RvID0gInRlc3QiLCB2YWx1ZXNfdG8gPSAic2NvcmUiKSAlPiUNCiAgbXV0YXRlKHNjb3JlID0gcm91bmQoc2NvcmUsIDIpKSAlPiUNCiAgbXV0YXRlKHNjb3JlID0gZmFjdG9yKHNjb3JlLCBsZXZlbHMgPSByZXYoc29ydCh1bmlxdWUoc2NvcmUpKSkpKSAlPiUNCiAgbXV0YXRlKHNjb3JlID0gY3V0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHNjb3JlKSksIGJyZWFrcyA9IHNlcSgxLDcsMC41KSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBzY29yZSkpICsNCiAgZ2VvbV9iYXIoYWVzKGZpbGwgPSB0ZXN0KSwgYWxwaGEgPSAwLjMsIHBvc2l0aW9uID0gImlkZW50aXR5IikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEwMDAsIDEwKSkrDQogICAgc2NhbGVfeF9kaXNjcmV0ZShuYS50cmFuc2xhdGUgPSBGKSsNCiAgI2Nvb3JkX2ZsaXAoKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIHNjb3JlIG1veWVuIikgKw0KICB0aGVtZSh0aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkNCg0KZ2dwbG90bHkoKQ0KDQpgYGANCg0KSidhaSB1biBwZXUgcmVmb3JtYXR0w6kgbGUgdGFibGVhdSBzdWl2YW50IHF1ZSBqJ2F2YWlzIGTDqWrDoCBmYWl0Lg0KDQpgYGB7cn0NCiMgQ3JlYXRpbmcgdGFibGUgcGFpcmVkX3F1ZXN0aW9ubmFpcmVzDQp0YWJfcGFpcmVkX3F1ZXN0aW9ubmFpcmVzIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KGlkLCBmaWxpZXJlKSAlPiUNCiAgc3VtbWFyaXNlKG4gPSBuKCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICBhcnJhbmdlKGRlc2MobikpICUkJQ0KICB0YWJsZShmaWxpZXJlLCBuKSAlPiUNCiAgZGF0YS5mcmFtZSgpICU+JQ0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gbiwgdmFsdWVzX2Zyb20gPSBGcmVxKSAlPiUNCiAgc2V0TmFtZXMoYygiRmlsaWVyZSIsICJUZXN0cyBub24gYXBwYXJpZXMiLCAiVGVzdHMgYXBwYXJpZXMiKSkNCg0KDQpkYXRhICU+JQ0KICBncm91cF9ieShmaWxpZXJlKSAlPiUNCiAgc3VtbWFyaXNlKGlkID0gbl9kaXN0aW5jdChpZCksIA0KICAgICAgICAgICAgdmFsZXVyc19tYW5xdWFudGVzID0gYXMuaW50ZWdlcihzdW0obmFfY291bnRzLG5hLnJtPVQpKQ0KICApICU+JQ0KICBsZWZ0X2pvaW4odGFiX3BhaXJlZF9xdWVzdGlvbm5haXJlcywgYnkgPSBjKCJmaWxpZXJlIiA9ICJGaWxpZXJlIikpICU+JSANCiAgYWRvcm5fdG90YWxzKCkgJT4lIA0KICByb3d3aXNlICU+JSANCiAgbXV0YXRlKG5iX3F1ZXN0aW9ubmFpcmVzID0gc3VtKGlkLCBgVGVzdHMgYXBwYXJpZXNgLCBuYS5ybT1UKSkgICU+JSANCiAgcmVsb2NhdGUoIm5iX3F1ZXN0aW9ubmFpcmVzIiwgLmFmdGVyID0gImlkIikgJT4lIA0KICB1bmdyb3VwICU+JSANCiAgbXV0YXRlKGFjcm9zcyhjKGlkOmBUZXN0cyBhcHBhcmllc2ApLA0KICAgICAgICAgICAgICAgIH5wYXN0ZTAoLngsICIgKCIsIHJvdW5kKC4qMTAwL3N1bSguWzE6N10sbmEucm09VCksMiksICIlKSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIiIpKSwNCiAgICAgICAgIA0KICAgICAgKSAlPiUgDQogIHNlbGVjdCgtZW5kc193aXRoKCIlIikpICU+JQ0KICBrYWJsZSAlPiUgDQogIGthYmxlX3BhcGVyKCkNCiAgIyBkYXRhdGFibGUob3B0aW9ucyA9IGxpc3QoDQogICMgICBwYWdlTGVuZ3RoID0gMTAsDQogICMgICBzY3JvbGxYID0gVFJVRSwNCiAgIyAgIHdpZHRoID0gImF1dG8iLA0KICAjICAgc2Nyb2xsWCA9IFRSVUUNCiAgIyApKQ0KYGBgDQoNCiMgSURzIGFwcGFyacOpcyB7LnRhYnNldH0NCg0KIyMgUG9wdWxhdGlvbiBldCBkaXN0cmlidXRpb24gcGFyIGZpbGnDqHJlDQoNCmBgYHtyIGZpbHRybyBxdWVzdGlvbmFyaSBhcHBhcmllfQ0KIyBjcmVhdGluZyBwb3B1bGF0aW9uDQppZF9pbmRleCA9IGRhdGEgJT4lIGdyb3VwX2J5KGlkKSAlPiUgY291bnQgJT4lIGZpbHRlcihuPT0yKSAlPiUgcHVsbChpZCkNCg0KZGF0YSA9IGRhdGEgJT4lIGZpbHRlcihpZCAlaW4lIGlkX2luZGV4KQ0KDQojIHRhYmxlIGRlc2NyaWJpbmcgcG9wdWxhdGlvbg0KZGF0YSAlPiUNCiAgZ3JvdXBfYnkoZmlsaWVyZSkgJT4lDQogIHN1bW1hcmlzZShpZCA9IG5fZGlzdGluY3QoaWQpLCANCiAgICAgICAgICAgIHZhbGV1cnNfbWFucXVhbnRlcyA9IGFzLmludGVnZXIoc3VtKG5hX2NvdW50cyxuYS5ybT1UKSkNCiAgKSAlPiUNCiAgYWRvcm5fdG90YWxzKCkgJT4lIA0KICByb3d3aXNlICU+JSANCiAgbXV0YXRlKG5iX3F1ZXN0aW9ubmFpcmVzID0gaWQqMikgICU+JSANCiAgcmVsb2NhdGUoIm5iX3F1ZXN0aW9ubmFpcmVzIiwgLmFmdGVyID0gImlkIikgJT4lIA0KICB1bmdyb3VwICU+JSANCiAgbXV0YXRlKGFjcm9zcyhjKGlkOnZhbGV1cnNfbWFucXVhbnRlcyksDQogICAgICAgICAgICAgICAgfnBhc3RlMCgueCwgIiAoIiwgcm91bmQoLioxMDAvc3VtKC5bMTo2XSxuYS5ybT1UKSwyKSwgIiUpIiwgDQogICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiIikpLA0KICAgICAgICAgDQogICAgICApICU+JSANCiAgc2VsZWN0KC1lbmRzX3dpdGgoIiUiKSkgJT4lIA0KICBrbml0cjo6a2FibGUoY2FwdGlvbiA9ICIgPGI+UG9wdWxhdGlvbiBkZSB0ZXN0cyBhcHBhcmnDqXM8Yj4iKSAlPiUNCiAga2FibGVfcGFwZXIoKQ0KDQoNCg0KYGBgDQoNCiMjIERvbm7DqWVzIG1hbnF1YW50ZXMNCg0KYGBge3IgdGVzdHMgYXBwYXJpw6lzIE5Bc30NCnRhYmxlKGRhdGEkbmFfY291bnRzKSAlPiUgDQogICAgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgICBtdXRhdGUoIiUiID0gcm91bmQoYXMubnVtZXJpYyhGcmVxL3N1bShGcmVxKSoxMDApLCAyKSwNCiAgICAgICAgICAgVmFyMSA9IHJvdW5kKGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKFZhcjEpKSwyKSkgJT4lIA0KICAgIHJlbmFtZSgiTmIgbWlzc2luZyB2YWx1ZXMiID0gVmFyMSkgJT4lIA0KICAgIGthYmxlKGNhcHRpb24gPSAiIDxiPk5iIGRlIHZhbGV1cnMgbWFucXVhbnRlcyBwYXIgcXVlc3Rpb25uYWlyZTxiPiIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKCkgJT4lIA0KICBrYWJsZV9wYXBlcigpIA0KDQphcHBseShkYXRhLDIsZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkgJT4lIA0KICBkYXRhLmZyYW1lKCkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigpICU+JSANCiAgcmVuYW1lKCJ2YXJpYWJsZSIgPSAicm93bmFtZSIsICJuIj0gIi4iKSAlPiUgDQogIGRhdGF0YWJsZShvcHRpb25zID0gbGlzdCgNCiAgICBwYWdlTGVuZ3RoID0gMTAsDQogICAgc2Nyb2xsWCA9IFRSVUUsDQogICAgd2lkdGggPSAiYXV0byIsDQogICAgc2Nyb2xsWCA9IFQNCiAgICApLA0KICAgIGNhcHRpb24gPSAiTWlzc2luZyB2YWx1ZXMgYnkgdmFyaWFibGUiKQ0KDQpgYGANCg0KIyMgRGlzdHJpYnV0aW9uIHNjb3JlIG1veWVuDQoNCiMjIyBQYXIgcXVlc3Rpb24NCg0KYGBge3IgZ2ZkZmdkZmd9DQpkYXRhICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBzMXExOnM3cTIsIG5hbWVzX3RvID0gInF1ZXN0aW9uIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lIA0KICBncm91cF9ieShxdWVzdGlvbikgJT4lIA0KICBzdW1tYXJpc2UoZGVzY3JpYmUoZmFzdD1ULCB2YWx1ZSkpICU+JSB1bmdyb3VwKCkgJT4lIA0KICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLHJvdW5kLDMpKSAlPiUgDQogIGRhdGF0YWJsZShvcHRpb25zID0gbGlzdCgNCiAgICBwYWdlTGVuZ3RoID0gMTAsDQogICAgc2Nyb2xsWCA9IFRSVUUsDQogICAgd2lkdGggPSAiYXV0byIsDQogICAgc2Nyb2xsWCA9IFRSVUUpLA0KICAgIGNhcHRpb24gPSAiIFRlc3RzIGFwcGFyacOpcyAtIFNjb3JlIC0gTcOpc3VyZXMgZGUgZGlzdHJpYnV0aW9uIHBhciBxdWVzdGlvbiINCiAgKQ0KICANCmBgYA0KDQpgYGB7ciBhc2RmYWRhfQ0KcmJpbmQoZGVzY3JpYmUoZGF0YSRzY29yZSwgZmFzdCA9IFQpLA0KICAgICAgZGVzY3JpYmUoZGF0YSRzY29yZVtkYXRhJHRlc3Q9PSJwcmUiXSwgZmFzdCA9IFQpLA0KICAgICAgZGVzY3JpYmUoZGF0YSRzY29yZVtkYXRhJHRlc3Q9PSJwb3N0Il0sIGZhc3QgPSBUKSkgJT4lIA0KICAgIGFzLmRhdGEuZnJhbWUocm93Lm5hbWVzID0gYygiRW5zZW1ibGUiLCAicHJlIiwgInBvc3QiKSkgJT4lDQogICAgcmVuYW1lKGRldmlhdGlvbl9zdGFuZGFyZCA9IHNkLCBlY2FydF90eXBlID0gc2UpICU+JSANCiAgICBzZWxlY3QoLXZhcnMpICU+JSANCiAgICBrYWJsZShjYXB0aW9uID0gIjxiPlRlc3RzIGFwcGFyacOpcyAtIE1lc3VyZXMgZGUgZGlzcGVyc2lvbjxiPiIsIA0KICAgICAgICAgIGRpZ2l0cyA9IDMpICU+JQ0KICAgIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IFQsICkgJT4lIA0KICAgIGthYmxlX3BhcGVyKCkNCmBgYA0KDQpgYGB7cn0NCmRhdGEgJT4lIA0KICBncm91cF9ieShmaWxpZXJlLHRlc3QpICU+JSANCiAgc3VtbWFyaXNlKGRlc2NyaWJlKHNjb3JlLCBmYXN0ID0gVCkpICU+JSB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoLWZpbGllcmUsIC12YXJzKSAlPiUgDQogIGthYmxlKGRpZ2l0PTMsIGNhcHRpb24gPSAiPGI+VGVzdHMgYXBwYXJpw6lzIC0gTWVzdXJlcyBkZSBkaXNwZXJzaW9uIGJ5IGZpbGnDqHJlPGI+IikgJT4lDQogIHBhY2tfcm93cyhpbmRleCA9IGMoIklERSI9MiwgDQogICAgICAgICAgICAgICAgICAgICAgIk1haWV1dGlxdWUiID0gMiwNCiAgICAgICAgICAgICAgICAgICAgICAiTWVkZWNpbmUgZ2VuZXJhbGUiID0gMiwNCiAgICAgICAgICAgICAgICAgICAgICAiTUtFIiA9IDIsDQogICAgICAgICAgICAgICAgICAgICAgIk9ydGhvcGhvbmllIiA9IDIsDQogICAgICAgICAgICAgICAgICAgICAgIlBoYXJtYWNpZSIgPSAyKSkgJT4lIA0KICBrYWJsZV9wYXBlcigpDQpgYGANCg0KIyMjIFBhciBxdWVzdGlvbm5haXJlDQoNCmBgYHtyfQ0KZyA9IGRhdGEgJT4lIA0KICBtdXRhdGUoc2NvcmUgPSByb3VuZChzY29yZSwgMikpICU+JQ0KICBtdXRhdGUoc2NvcmUgPSBmYWN0b3Ioc2NvcmUsIGxldmVscyA9IHJldihzb3J0KHVuaXF1ZShzY29yZSkpKSkpICU+JQ0KICBtdXRhdGUoc2NvcmUgPSBjdXQoYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoc2NvcmUpKSwgYnJlYWtzID0gc2VxKDEsNywwLjUpKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IHNjb3JlKSkgKw0KICBnZW9tX2JhcihhZXMoZmlsbCA9IHRlc3QpLCBhbHBoYSA9IDAuMywgcG9zaXRpb24gPSAiaWRlbnRpdHkiKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTAwMCwgMTApKSsNCiAgICBzY2FsZV94X2Rpc2NyZXRlKG5hLnRyYW5zbGF0ZSA9IEYpKw0KICAjY29vcmRfZmxpcCgpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gc2NvcmUgbW95ZW4iKSArDQogIHRoZW1lKHRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKQ0KDQpnZ3Bsb3RseShnKQ0KYGBgDQoNCiMjIyMgUGFyIHF1ZXN0aW9ubmFpcmUgYnkgZmlsacOocmUNCg0KYGBge3J9DQpnID0gZGF0YSAlPiUgDQogIyBwaXZvdF9sb25nZXIoY29scyA9IGMoInBvc3QiLCAicHJlIiksIG5hbWVzX3RvID0gInRlc3QiLCB2YWx1ZXNfdG8gPSAic2NvcmUiKSAlPiUNCiAgbXV0YXRlKHNjb3JlID0gcm91bmQoc2NvcmUsIDIpKSAlPiUNCiAgbXV0YXRlKHNjb3JlID0gZmFjdG9yKHNjb3JlLCBsZXZlbHMgPSByZXYoc29ydCh1bmlxdWUoc2NvcmUpKSkpKSAlPiUNCiAgbXV0YXRlKHNjb3JlID0gY3V0KGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHNjb3JlKSksIGJyZWFrcyA9IHNlcSgxLDcsMC41KSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBzY29yZSkpICsNCiAgZ2VvbV9iYXIoYWVzKGZpbGwgPSB0ZXN0KSwgYWxwaGEgPSAwLjMsIHBvc2l0aW9uID0gImlkZW50aXR5IikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEwMDAsIDEwKSkrDQogICAgc2NhbGVfeF9kaXNjcmV0ZShuYS50cmFuc2xhdGUgPSBGKSsNCiAgY29vcmRfZmxpcCgpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gc2NvcmUgbW95ZW4iLA0KICAgICAgIGZpbGwgPSAiVGVzdCIpICsNCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpKw0KICBmYWNldF93cmFwKH5maWxpZXJlKQ0KDQpnZ3Bsb3RseShnKQ0KYGBgDQoNCiMgVGVzdHMgc3RhdCB7LnRhYnNldH0NCg0KIyMgVGVzdCBkZSBXaWxjb3hvbiBzdXIgZG9ubsOpZXMgYXBwYXJpw6llcw0KDQpgYGB7ciB0LXRlc3RfdG91c19jb25mb25kdXN9DQojIERGIHdpdGggaWQtZmlsaWVyZS1wcmUtcG9zdCBwb3VyIGxlcyB0ZXN0cyBzdGF0DQpwYWlyZWRfZGF0YSA8LSBkYXRhICU+JSANCiAgcmVsb2NhdGUodGVzdCwgLmFmdGVyPWxhc3RfY29sKCkpICU+JQ0KICBzZWxlY3QoLShzMXExOm5hX2NvdW50cykpICU+JQ0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gInRlc3QiLCB2YWx1ZXNfZnJvbSA9ICJzY29yZSIpDQoNCmBgYA0KDQpQb3VyIHJlYWxpc2VyIHVuIHRlc3QgZGUgc3R1ZGVudCwgdW5lIHBhcm1pIGxlcyBwbHVzaWV1cnMgY29uZGl0aW9ucyBkZSB2YWxpZGl0w6kgZXN0IHF1ZSBsYSB2YXJpYWJsZSBxdSdvbiDDqXR1ZGllIGRvaXQgc3VpdnJlIGxhICpsb2kgbm9ybWFsZSo6IHNhIGRpc3RyaWJ1dGlvbiBhIHVuZSBmb3JtZSBlbiBjbG9jaGUgc2ltbWV0cmlxdWUuIE9yLCBvbiBhIHZ1IMOgIGxhIGZpbiBkdSBjaGFwaXRyZSAzIHF1ZSBjZSBuJ2VzdCBwYXMgZHUgdG91dCBsZSBjYXMuIENlbGEgbm91cyByZW5kICJpbXBvc3NpYmxlIiAoIiIgcGFyY2UgcXVlIGVuIHZyYWkgamUgcGV1eCBxdWFuZCBtZW1lIGxlIGxhbmNlciBzYW5zIHNvdWNpcyBsZSB0ZXN0IGV0IHRyw6hzIHByb2JhYmxlbWVudCBwZXJzb25uZSB0ZSBkZW1hbmRlcmFpdCBzaSB0dSBhcyB2ZXJpZmnDqSBsZXMgY29uZGl0aW9ucyBkZSB2YWxpZGl0w6kgZHUgdGVzdCkgdXRpbGlzZXIgbGUgKnQgc3R1ZGVudCogZXQgb24gdmEgZGV2b2lyICJzZSBjb250ZW50ZXIiIGQndW4gdGVzdCAqbm9uLXBhcmFtZXRyaXF1ZSogKHF1YW5kIGxhIHZhcmlhYmxlIMOpdHVkaWUgbmUgc3VpdCBwYXMgdW5lIGRpc3RyaWJ1dGlvbiBwcsOpY2lzZSwgY29tbWUgbGEgbG9pIG5vcm1hbGUgcGFyIGV4YW1wbGUpLg0KDQpMJ2VxdWl2YWxlbnQgbm9uIHBhcmFtZXRyaXF1ZSBkdSAqdCBzdHVkZW50IGFwcGFyacOpKiBlc3QgbGUgdGVzdCBkZSByYW5nIHNpZ27DqSBkZSB3aWxjb3hvbiBhdmVjIGNvcnJlY3Rpb24gZGUgY29udGludWl0w6kuIEplIG1lIHJlcMOodGUsIGxlIHRlc3QgZHUgcmFuZyBzaWduw6kgZGUgV2lsY294b24gZXN0IHVuIHRlc3Qgc3RhdGlzdGlxdWUgbm9uIHBhcmFtw6l0cmlxdWUgcXVpIGNvbXBhcmUgZGV1eCDDqWNoYW50aWxsb25zIGFwcGFyZW50w6lzIG91IGRlcyBtZXN1cmVzIHLDqXDDqXTDqWVzIHN1ciB1biBzZXVsIMOpY2hhbnRpbGxvbiBhZmluIGQnw6l2YWx1ZXIgc2kgbGVzIHJhbmdzIG1veWVucyBkZSBsZXVyIHBvcHVsYXRpb24gZGlmZsOocmVudCAoYydlc3Qtw6AtZGlyZSBxdSdpbCBzJ2FnaXQgZCd1biB0ZXN0IGRlIGRpZmbDqXJlbmNlIHBhciBwYWlyZXMpLiBJbCBwZXV0IMOqdHJlIHV0aWxpc8OpIGNvbW1lIGFsdGVybmF0aXZlIGF1IHRlc3QgdCBkZSBTdHVkZW50IGxvcnNxdWUgbGEgcG9wdWxhdGlvbiBuZSBwZXV0IHBhcyDDqnRyZSBzdXBwb3PDqWUgbm9ybWFsZW1lbnQgZGlzdHJpYnXDqWUuDQoNCkVuIHN0YXRpc3RpcXVlLCBsZSAicmFuZyIgZmFpdCByw6lmw6lyZW5jZSDDoCBsYSBwb3NpdGlvbiBkJ3VuZSB2YWxldXIgcGFydGljdWxpw6hyZSBhdSBzZWluIGQndW4gZW5zZW1ibGUgZGUgZG9ubsOpZXMgbG9yc3F1J2VsbGVzIHNvbnQgY2xhc3PDqWVzIHBhciBvcmRyZSBjcm9pc3NhbnQgb3UgZMOpY3JvaXNzYW50Lg0KDQpQYXIgZXhlbXBsZSwgY29uc2lkw6lyb25zIGwnZW5zZW1ibGUgZGUgZG9ubsOpZXMgc3VpdmFudCA6IHszLCA3LCAxLCA0LCA2fS4gU2kgbm91cyBsZSBjbGFzc29ucyBwYXIgb3JkcmUgY3JvaXNzYW50LCBub3VzIG9idGVub25zIHsxLCAzLCA0LCA2LCA3fS4gTGUgInJhbmciIGRlIGNoYXF1ZSBub21icmUgZGFucyBsJ2Vuc2VtYmxlIGRlIGRvbm7DqWVzIG9yaWdpbmFsIGVzdCBhbG9ycyBzYSBwb3NpdGlvbiBkYW5zIGwnZW5zZW1ibGUgZGUgZG9ubsOpZXMgb3Jkb25uw6kuIEFpbnNpLCBsZSByYW5nIGRlIDMgZXN0IDIsIGxlIHJhbmcgZGUgNyBlc3QgNSwgbGUgcmFuZyBkZSAxIGVzdCAxLCBsZSByYW5nIGRlIDQgZXN0IDMgZXQgbGUgcmFuZyBkZSA2IGVzdCA0Lg0KDQpEYW5zIGxlIGNhZHJlIGR1IHRlc3QgZHUgcmFuZyBzaWduw6kgZGUgV2lsY294b24sIGxlcyBkaWZmw6lyZW5jZXMgZW50cmUgZGVzIG9ic2VydmF0aW9ucyBhcHBhcmnDqWVzIHNvbnQgY2xhc3PDqWVzIGVuIGZvbmN0aW9uIGRlIGxldXIgdmFsZXVyIGFic29sdWUuIExlIHNpZ25lIGRlIGxhIGRpZmbDqXJlbmNlIGVzdCBlbnN1aXRlIGFwcGxpcXXDqSBhdSByYW5nLiBDZWxhIHBlcm1ldCBhdSB0ZXN0IGRlIHByZW5kcmUgZW4gY29tcHRlIMOgIGxhIGZvaXMgbCdhbXBsZXVyIGRlcyBkaWZmw6lyZW5jZXMgKHBhciBsZSBiaWFpcyBkZXMgcmFuZ3MgZGVzIGRpZmbDqXJlbmNlcyBhYnNvbHVlcykgZXQgbGUgc2VucyBkZXMgZGlmZsOpcmVuY2VzIChwYXIgbGUgYmlhaXMgZGVzIHNpZ25lcykuDQoNClBlbnNlIMOgIGwnRUNOOiBvbiB2ZXV0IGNvbXBhcmVyIGxhIHBlcmZvcm1hbmNlIGRlcyDDqWzDqXZlcyBkZSAyIGx5Y8OpZXMuIExlIHRlc3QgZGUgd2lsY294b24gcG91cnJhaXQgbm91cyBhaWRlciDDoCByw6lwb25kcmUgw6AgbGEgcXVlc3Rpb24gImVzdC1jZSBxdWUgc2kgbGUgY2xhc3NlbWVudCAocmFuZykgbWVkaWFuIGRlcyDDqWzDqHZlcyBkJ3VuIGx5Y8OpZSBYIG91IFkgZXN0IG1laWxsZXVyZSBxdWUgbGUgY2xhc3NlbWVudCAocmFuZykgbWVkaWFuIGRlIGwnYXV0cmUuDQoNCkplIHZhaXMgbGFuY2VyIGxlIHRlc3Qgc3VyIGwnZW5zZW1ibGUgZGUgbGEgcG9wdWxhdGlvbiBldCB0J2V4cGxpcXVlciBsZSByw6lzdWx0YXQuDQoNCmBgYHtyfQ0Kd2lsY294LnRlc3QocGFpcmVkX2RhdGEkcG9zdCwNCiAgICAgICAgICAgICAgICAgICAgICAgIHBhaXJlZF9kYXRhJHByZSwgcGFpcmVkID0gVA0KICAgICAgICAgICAgICAgICAgICAgICApDQoNCg0KIyB0LnRlc3QocGFpcmVkX2RhdGEkcG9zdCxwYWlyZWRfZGF0YSRwcmUscGFpcmVkID0gVCwgdmFyLmVxdWFsID0gRikNCmBgYA0KDQotICAgKioiVGVzdCBkZSByYW5nIHNpZ27DqSBkZSBXaWxjb3hvbiBhdmVjIGNvcnJlY3Rpb24gZGUgY29udGludWl0w6kiKiogOiBDZWNpIGluZGlxdWUgbGUgdGVzdCBzcMOpY2lmaXF1ZSB1dGlsaXPDqS4gTGEgcGFydGllICJjb3JyZWN0aW9uIGRlIGNvbnRpbnVpdMOpIiBlc3QgdW5lIHRlY2huaXF1ZSBwZXJtZXR0YW50IGQnYWp1c3RlciBsZSB0ZXN0IGRlIHJhbmcgc2lnbsOpIGRlIFdpbGNveG9uIHBvdXIgdGVuaXIgY29tcHRlIGR1IGZhaXQgcXVlIG5vdXMgdXRpbGlzb25zIHVuZSB2ZXJzaW9uIGRpc2Nyw6h0ZSBkJ3VuZSBkaXN0cmlidXRpb24gY29udGludWUuDQoNCi0gICAqKiJEb25uw6llcyA6IHBhaXJlZF9kYXRhXCRwb3N0IGV0IHBhaXJlZF9kYXRhXCRwcmUiKiogOiBDZWNpIHNww6ljaWZpZSBsZXMgZGV1eCBlbnNlbWJsZXMgZGUgbWVzdXJlcyBvdSBkJ29ic2VydmF0aW9ucyBxdWkgb250IMOpdMOpIGNvbXBhcsOpcyBkYW5zIGxlIHRlc3QuDQoNCi0gICAqKiJWID0gNTIxNzEiKio6IElsIHMnYWdpdCBkZSBsYSBzdGF0aXN0aXF1ZSBkdSB0ZXN0LiBQb3VyIGxlIHRlc3QgZHUgcmFuZyBzaWduw6kgZGUgV2lsY294b24sIGlsIHMnYWdpdCBkZSBsYSBzb21tZSBkZXMgcmFuZ3MgZGVzIGRpZmbDqXJlbmNlcyBwb3NpdGl2ZXMgKG91IGRlIGxhIHNvbW1lIGRlcyByYW5ncyBuw6lnYXRpZnMsIHNlbG9uIGxlIGxvZ2ljaWVsIHV0aWxpc8OpKS4NCg0KLSAgICoqInAtdmFsdWUgXDwgMi4yZS0xNiIqKiA6IElsIHMnYWdpdCBkZSBsYSB2YWxldXIgcCBkdSB0ZXN0LCBxdWkgZXN0IHV0aWxpc8OpZSBwb3VyIGludGVycHLDqXRlciBsZXMgcsOpc3VsdGF0cy4gU2kgbGEgdmFsZXVyIHAgZXN0IGluZsOpcmlldXJlIGF1IHNldWlsIGRlIHNpZ25pZmljYXRpb24gY2hvaXNpIChzb3V2ZW50IDAsMDUpLCBsJ2h5cG90aMOoc2UgbnVsbGUgZXN0IHJlamV0w6llLiBEYW5zIGNlIGNhcywgbGEgdmFsZXVyIHAgZXN0IGV4dHLDqm1lbWVudCBmYWlibGUsIGV0IGlsIHkgYSBkb25jIGRlIGJvbm5lcyByYWlzb25zIGRlIHJlamV0ZXIgbCdoeXBvdGjDqHNlIG51bGxlLg0KDQotICAgKioiSHlwb3Row6hzZSBhbHRlcm5hdGl2ZSA6IGxlIHbDqXJpdGFibGUgZGlzdGFuY2UgZW50cmUgbGVzIDIgbWVkaWFuZXMgbidlc3QgcGFzIMOpZ2FsIMOgIDAiKiogOiBJbCBzJ2FnaXQgZGUgbCdoeXBvdGjDqHNlIGFsdGVybmF0aXZlIGR1IHRlc3QuIFBvdXIgbGUgdGVzdCBkdSByYW5nIHNpZ27DqSBkZSBXaWxjb3hvbiwgbCdoeXBvdGjDqHNlIG51bGxlIGVzdCBxdWUgbGEgbcOpZGlhbmUgZGVzIGRpZmbDqXJlbmNlcyBlbnRyZSBsZXMgcGFpcmVzIGQnb2JzZXJ2YXRpb25zIGVzdCDDqWdhbGUgw6AgesOpcm8uIENldHRlIGh5cG90aMOoc2UgYWx0ZXJuYXRpdmUgaW5kaXF1ZSBxdWUgbGEgdsOpcml0YWJsZSBtw6lkaWFuZSBkZXMgZGlmZsOpcmVuY2VzIG4nZXN0IHBhcyBudWxsZS4NCg0KRW4gdGVybWVzIHNpbXBsZXMsIGxlIHRlc3QgaW5kaXF1ZSBxdSdpbCBleGlzdGUgdW5lIGRpZmbDqXJlbmNlIHN0YXRpc3RpcXVlbWVudCBzaWduaWZpY2F0aXZlIGVudHJlIGxlcyBtZXN1cmVzIGF2YW50IGV0IGFwcsOocyBkYW5zIGNlcyBkb25uw6llcyBhcHBhcmnDqWVzLCBhdmVjIHVuZSB2YWxldXIgcCB0csOocyBmYWlibGUgKFw8MC4wMDEpIGZvdXJuaXNzYW50IHVuZSBwcmV1dmUgc29saWRlIGNvbnRyZSBsJ2h5cG90aMOoc2UgbnVsbGUuDQoNCkplIHZhaXMgZmFpcmUgbGEgbcOqbWUgY2hvc2UgcG91ciBjaGFxdWUgZmlsacOocmUgcHJpc2Ugc2luZ3VsacOocmVtZW50Lg0KDQpgYGB7ciB0LnRlc3RfYnlfZmlsaWVyZSwgZmlnLmhlaWdodD0xMH0NCiMgaW5pdGlhbGlzaW5nIGVtdHB0eSBsaXN0DQpyZXN1bHRzIDwtIGxpc3QoKQ0KDQojSXRlcmF0aW9uIG92ZXIgZmlsaWVyZQ0KICMgZm9yIChpbmRleCBpbiB1bmlxdWUoZGF0YSRmaWxpZXJlKSkgew0KICMgICB0ZXN0IDwtIHQudGVzdChwYWlyZWRfZGF0YSRwb3N0W3BhaXJlZF9kYXRhJGZpbGllcmUgPT0gaW5kZXhdLA0KICMgICAgIHBhaXJlZF9kYXRhJHByZVtwYWlyZWRfZGF0YSRmaWxpZXJlID09IGluZGV4XSwNCiAjICAgICBwYWlyZWQgPSBUUlVFLCB2YXIuZXF1YWwgPSBGDQogIyAgICkNCiAjIA0KICMgICByZXN1bHRzW1tpbmRleF1dIDwtIHRlc3QNCiAjIH0NCg0KIGZvciAoaW5kZXggaW4gdW5pcXVlKHBhaXJlZF9kYXRhJGZpbGllcmUpKSB7DQogICB0ZXN0IDwtIHdpbGNveC50ZXN0KHBhaXJlZF9kYXRhJHBvc3RbcGFpcmVkX2RhdGEkZmlsaWVyZSA9PSBpbmRleF0sDQogICAgIHBhaXJlZF9kYXRhJHByZVtwYWlyZWRfZGF0YSRmaWxpZXJlID09IGluZGV4XSwNCiAgICAgcGFpcmVkID0gVA0KICAgICAjLHZhci5lcXVhbCA9IEYNCiAgICkNCg0KICAgcmVzdWx0c1tbaW5kZXhdXSA8LSB0ZXN0DQogfQ0KDQoNCiAjIEZvcm1hdHRpbmcgcmVzdWx0cw0KIHJlc3VsdF9kZiA8LSBsYXBwbHkocmVzdWx0cywgZnVuY3Rpb24odGVzdCkgew0KICAgZGF0YS5mcmFtZSgNCiAgICAgICAjIG1lYW5fc2NvcmVfZGlmZmVyZW5jZSA9IHRlc3QkZXN0aW1hdGUsDQogICAgICAgcC52YWx1ZSA9IHB2YWxfZm9ybWF0KHRlc3QkcC52YWx1ZSksDQogICAgICAgI2NvbmYgPSB0ZXN0JGNvbmYuaW50LA0KICAgICAgICNsb3dfaGlnaF90YWcgPSByZXAoYygiY29uZi5sb3ciLCJjb25mLmhpZ2giKSksDQogICAgICAgbWV0aG9kID0gdGVzdCRtZXRob2QNCiAgICAgICApDQogICAgIH0NCiAgICkNCg0KICMgTWVyZ2UgdGhlIGRhdGEgZnJhbWVzIGluIHRoZSBsaXN0DQogbWVyZ2VkX2RmIDwtIGJpbmRfcm93cyhyZXN1bHRfZGYsIC5pZCA9ICJmaWxpZXJlIikNCg0KIG1lcmdlZF9kZiAlPiUga2FibGUgJT4lIGthYmxlX3BhcGVyKCkNCiANCmBgYA0KDQojIyBUZXN0IGRlIHBlcm11dGF0aW9uDQoNCmBgYHtyIG1lc3NhZ2U9Rn0NCiMgSW5zdGFsbCBhbmQgbG9hZCB0aGUgImV4YWN0UmFua1Rlc3RzIiBwYWNrYWdlDQpsaWJyYXJ5KGV4YWN0UmFua1Rlc3RzKQ0KDQojIFNldCB1cCB5b3VyIHBhaXJlZCBkYXRhDQpncm91cDEgPC0gYygzLCA0LCAyLCAxKSAgICMgU2FtcGxlIDENCmdyb3VwMiA8LSBjKDQsIDUsIDIsIDMpICAgIyBTYW1wbGUgMg0KDQojIENhbGN1bGF0ZSB0aGUgb2JzZXJ2ZWQgdGVzdCBzdGF0aXN0aWMNCm9ic2VydmVkX3N0YXRpc3RpYyA8LSBtZWFuKHBhaXJlZF9kYXRhJHBvc3QgLSBwYWlyZWRfZGF0YSRwcmUpICAjIE1lYW4gZGlmZmVyZW5jZSBhcyBhbiBleGFtcGxlDQoNCiMgU2V0IHRoZSBudW1iZXIgb2YgcGVybXV0YXRpb25zDQpuX3Blcm11dGF0aW9ucyA8LSAxMDAwMDANCg0KIyBQZXJmb3JtIHRoZSBwYWlyZWQgcGVybXV0YXRpb24gdGVzdA0KcGVybV9yZXN1bHQgPC0gcGVybS50ZXN0KHBhaXJlZF9kYXRhJHBvc3QsIHBhaXJlZF9kYXRhJHByZSwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImV4YWN0IiwgZXhhY3Rfb3B0aW9ucyA9IGxpc3QobnBlcm0gPSBuX3Blcm11dGF0aW9ucykpDQoNCiMgRXh0cmFjdCB0aGUgcC12YWx1ZSBmcm9tIHRoZSBwZXJtdXRhdGlvbiB0ZXN0IHJlc3VsdA0KcF92YWx1ZSA8LSBwZXJtX3Jlc3VsdCRwLnZhbHVlDQoNCiMgUHJpbnQgdGhlIG9ic2VydmVkIHRlc3Qgc3RhdGlzdGljIGFuZCBwLXZhbHVlDQpjYXQoIk9ic2VydmVkIHRlc3Qgc3RhdGlzdGljOiIsIG9ic2VydmVkX3N0YXRpc3RpYywgIlxuIikNCmNhdCgiUC12YWx1ZToiLCBwdmFsX2Zvcm1hdChwX3ZhbHVlKSwgIlxuIikNCg0KYGBgDQoNClZvaWNpIGNvbW1lbnQgZm9uY3Rpb25uZSB1biB0ZXN0IGRlIHBlcm11dGF0aW9uLCDDqXRhcGUgcGFyIMOpdGFwZSA6DQoNCkZvcm11bGVyIGwnaHlwb3Row6hzZSA6IG9uIGNvbW1lbmNlIHBhciDDqW5vbmNlciBsJ2h5cG90aMOoc2UgbnVsbGUgKEjigoApIGV0IGwnaHlwb3Row6hzZSBhbHRlcm5hdGl2ZSAoSOKCgSkuIEwnaHlwb3Row6hzZSBudWxsZSBzdXBwb3NlIHF1J2lsIG4neSBhIHBhcyBkZSBkaWZmw6lyZW5jZSBlbnRyZSBsZXMgZ3JvdXBlcywgdGFuZGlzIHF1ZSBsJ2h5cG90aMOoc2UgYWx0ZXJuYXRpdmUgc3VnZ8OocmUgcXUnaWwgeSBhIHVuZSBkaWZmw6lyZW5jZSBzaWduaWZpY2F0aXZlLg0KDQpDb21iaW5lciBldCBtw6lsYW5nZXIgbGVzIGRvbm7DqWVzIDogUHJlbmV6IGxlcyBtZXN1cmVzIChoYXV0ZXVycykgZGVzIGRldXggZ3JvdXBlcyBldCBjb21iaW5lei1sZXMgZW4gdW4gc2V1bCBlbnNlbWJsZSBkZSBkb25uw6llcy4gRW5zdWl0ZSwgbcOpbGFuZ2V6IG91IHBlcm11dGV6IGF1IGhhc2FyZCBsZXMgw6l0aXF1ZXR0ZXMgKGdyb3VwZSBBIGV0IGdyb3VwZSBCKSBhc3NvY2nDqWVzIGF1eCBtZXN1cmVzLiBDZSBtw6lsYW5nZSByb21wdCB0b3V0ZSBhc3NvY2lhdGlvbiBlbnRyZSBsZXMgZ3JvdXBlcy4NCg0KUmVwZXRlciBsZXMgw6l0YXBlcyAyIGV0IDMgOiBSw6lww6l0ZXogbGVzIMOpdGFwZXMgMiBldCAzIHBsdXNpZXVycyBmb2lzIChwYXIgZXhlbXBsZSwgMSAwMDAgZm9pcyBvdSBwbHVzKSBwb3VyIGNyw6llciB1bmUgZGlzdHJpYnV0aW9uIGRlIHN0YXRpc3RpcXVlcyBkZSB0ZXN0IHNvdXMgbCdoeXBvdGjDqHNlIG51bGxlLiBDaGFxdWUgZm9pcyBxdWUgdm91cyBtw6lsYW5nZXogbGVzIGRvbm7DqWVzIGV0IGNhbGN1bGV6IGxhIHN0YXRpc3RpcXVlIGRlIHRlc3QsIHZvdXMgc2ltdWxleiBjZSBxdWkgc2UgcGFzc2VyYWl0IHMnaWwgbid5IGF2YWl0IHBhcyBkZSB2w6lyaXRhYmxlIGRpZmbDqXJlbmNlIGVudHJlIGxlcyBncm91cGVzLg0KDQpDb21wYXJleiBsYSBzdGF0aXN0aXF1ZSBkZSB0ZXN0IG9ic2VydsOpZSA6IE9uIGNvbXBhcmUgbGEgc3RhdGlzdGlxdWUgZGUgdGVzdCBvYnNlcnbDqWUgKGNhbGN1bMOpZSDDoCBwYXJ0aXIgZGVzIGRvbm7DqWVzIG9yaWdpbmFsZXMsIG5vbiBtw6lsYW5nw6llcykgw6AgbGEgZGlzdHJpYnV0aW9uIGRlcyBzdGF0aXN0aXF1ZXMgZGUgdGVzdCBvYnRlbnVlcyDDoCBwYXJ0aXIgZGVzIHBlcm11dGF0aW9ucy4gSWwgcydhZ2l0IGVzc2VudGllbGxlbWVudCBkZSBzZSBkZW1hbmRlciA6ICJRdWVsbGUgZXN0IGwnYW1wbGV1ciBkZSBsYSBzdGF0aXN0aXF1ZSBkZSB0ZXN0IG9ic2VydsOpZSBwYXIgcmFwcG9ydCDDoCBjZSBxdWUgbCdvbiBwb3VycmFpdCBhdHRlbmRyZSBkdSBzZXVsIGhhc2FyZCA/Ig0KDQpDYWxjdWxlciBsYSB2YWxldXIgcCA6IENhbGN1bGV6IGxhIHZhbGV1ciBwIGVuIGTDqXRlcm1pbmFudCBsYSBwcm9wb3J0aW9uIGRlIHN0YXRpc3RpcXVlcyBkZSB0ZXN0IHBlcm11dMOpZXMgcXVpIHNvbnQgcGx1cyBleHRyw6ptZXMgKHBsdXMgZ3JhbmRlcyBvdSBwbHVzIHBldGl0ZXMpIHF1ZSBsYSBzdGF0aXN0aXF1ZSBkZSB0ZXN0IG9ic2VydsOpZS4gQ2V0dGUgdmFsZXVyIHAgcmVwcsOpc2VudGUgbGEgcHJvYmFiaWxpdMOpIGQnb2JzZXJ2ZXIgdW5lIHN0YXRpc3RpcXVlIGRlIHRlc3QgYXVzc2kgZXh0csOqbWUsIG91IHBsdXMgZXh0csOqbWUsIHF1ZSBjZWxsZSBxdSdvbiBhIG9idGVudWUsIGVuIHN1cHBvc2FudCBxdWUgbCdoeXBvdGjDqHNlIG51bGxlIGVzdCB2cmFpZS4gVW5lIHBldGl0ZSB2YWxldXIgcCBzdWdnw6hyZSBxdSdpbCBlc3QgcGV1IHByb2JhYmxlIHF1ZSBsYSBkaWZmw6lyZW5jZSBvYnNlcnbDqWUgc29pdCBsZSBmcnVpdCBkdSBoYXNhcmQuDQoNClN1ciBsYSBiYXNlIGRlIGxhIHZhbGV1ciBwIGV0IGR1IG5pdmVhdSBkZSBzaWduaWZpY2F0aW9uIHF1J29uIGEgZMOpZmluaSAoaGFiaXR1ZWxsZW1lbnQgzrEgPSAwLDA1KSwgb24gZMOpY2lkZSBkZSByZWpldGVyIG91IG5vbiBsJ2h5cG90aMOoc2UgbnVsbGUuIFNpIGxhIHZhbGV1ciBwIGVzdCBpbmbDqXJpZXVyZSBhdSBzZXVpbCBkZSBzaWduaWZpY2F0aW9uLCBvbiByZWpldGUgbCdoeXBvdGjDqHNlIG51bGxlIGV0IGNvbmNsdWV6IHF1J2lsIGV4aXN0ZSBkZXMgcHJldXZlcyBkJ3VuZSBkaWZmw6lyZW5jZSBzaWduaWZpY2F0aXZlIGVudHJlIGxlcyBncm91cGVzLg0KDQpDJ2VzdCBsJ2lkw6llIGRlIGJhc2UgZCd1biB0ZXN0IGRlIHBlcm11dGF0aW9uLiBFbiBtw6lsYW5nZWFudCBhdSBoYXNhcmQgbGVzIMOpdGlxdWV0dGVzIGRlcyBncm91cGVzIGV0IGVuIGNvbXBhcmFudCBsYSBzdGF0aXN0aXF1ZSBkZSB0ZXN0IG9ic2VydsOpZSDDoCBsYSBkaXN0cmlidXRpb24gZGVzIHN0YXRpc3RpcXVlcyBkZSB0ZXN0IHBlcm11dMOpZXMsIGxlcyB0ZXN0cyBkZSBwZXJtdXRhdGlvbiBwZXJtZXR0ZW50IGQnw6l2YWx1ZXIgbGEgcHJvYmFiaWxpdMOpIGQnb2JzZXJ2ZXIgbGEgZGlmZsOpcmVuY2Ugb2JzZXJ2w6llIHNvdXMgbCdoeXBvdGjDqHNlIG51bGxlIGQnYWJzZW5jZSBkZSBkaWZmw6lyZW5jZS4gSWwgcydhZ2l0IGQndW5lIHRlY2huaXF1ZSBxdWkgbmUgcmVwb3NlIHBhcyBzdXIgZGVzIGh5cG90aMOoc2VzIHN0cmljdGVzIGNvbmNlcm5hbnQgbGEgZGlzdHJpYnV0aW9uIGRlcyBkb25uw6llcywgY2UgcXVpIGxhIHJlbmQgYXBwbGljYWJsZSDDoCB1biBsYXJnZSDDqXZlbnRhaWwgZGUgc2PDqW5hcmlvcy4gRG9uYyBvbiBhIHBhcyBsZSBwcm9ibMOobWUgZGUgbGEgbm9uLW5vcm1hbGl0w6kgY29tbWUgYXZlYyBsZSB0IHN0dWRlbnQgZXQgb24gYSBwYXMgbGUgcHJvYmzDqG1lIGRlcyBleCBhZXF1byBjb21tZSBhdmVjIHdpbGNveG9uLiBRdWFuZCBwb3NzaWJsZSwgaWwgZXN0IHByw6lmw6lyYWJsZSBhcHBsaXF1ZXIgbGVzIGF1dHJlcyB0ZXN0cyBwYXJjZSBxdSdpbHMgc29udCBwbHVzIHB1aXNzYW50cy4NCg0KDQojIEV4dHJhcw0KYGBge3IgbWVzc2FnZT1GfQ0KIyBSZWxvYWRpbmcgZGF0YSBhbmQgc3RhcnRpbmcgZnJvbSBzY3JhdGNoIChjYXVzZSBwcmV2aW91c2x5LCB0cmFuc2Zvcm1pbmcgYW5zd2VycyBpbnRvIG51bWJlcnMgZXJhc2VkICJOU1AicyktLS0tLS0tLS0tLS0tDQpwb3N0ID0gcmVhZC54bHN4KCJDb3BpZSBkZSByZXN1bHRhdHMgUTIgY29waWUueGxzeCIsIHNoZWV0ID0gMSkNCnByZSA9IHJlYWQueGxzeCgiQ29waWUgZGUgcmVzdWx0YXRzIFExIGNvcGllLnhsc3giLCBzaGVldCA9IDEpDQoNCmNvbG5hbWVzKHByZSkgPSB0b2xvd2VyKGNvbG5hbWVzKHByZSkpDQpjb2xuYW1lcyhwb3N0KSA9IHRvbG93ZXIoY29sbmFtZXMocG9zdCkpDQoNCiMgY2xlYW5pbmcgYW5kIHByZXBhcmluZyAicHJlIiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpwcmUgPSBwcmUgJT4lIA0KICAgIHNlbGVjdCgtY29udGFpbnMoYygiaWQiLCJzdWJtaXRkYXRlIiwibGFzdHBhZ2UiLCJzdGFydGxhbmd1YWdlIikpKSAlPiUgDQogICAgcmVuYW1lKCJmaWxpZXJlIj1iMSwgImlkIiA9IGExKSAlPiUgDQogICAgbXV0YXRlKHRlc3QgPSAicHJlIikgJT4lIA0KICAgIG11dGF0ZShhY3Jvc3MoczFxMTpzN3EyLCBhcy5jaGFyYWN0ZXIpKSAlPiUgDQogICAgbXV0YXRlKGZpbGllcmUgPSBjYXNlX3doZW4oZmlsaWVyZSA9PSAiw6l0dWRpYW50KGUpIGVuIG1hw69ldXRpcXVlIiB+ICJtYWlldXRpcXVlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxpZXJlID09ICLDqXR1ZGlhbnQoZSkgZW4gb3J0aG9waG9uaWUiIH4gIm9ydGhvcGhvbmllIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxpZXJlID09ICLDqXR1ZGlhbnQoZSkgZW4gcGhhcm1hY2llIiB+ICJwaGFybWFjaWUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGllcmUgPT0gIsOpdHVkaWFudChlKSBJREUiIH4gIklERSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsaWVyZSA9PSAiw6l0dWRpYW50KGUpIE1LRSIgfiAiTUtFIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxpZXJlID09ICJpbnRlcm5lIGRlIG3DqWRlY2luZSBnw6luw6lyYWxlIiB+ICJtZWRlY2luZSBnZW5lcmFsZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgICAgICAgICkNCg0KIyBjbGVhbmluZyBhbmQgcHJlcGFyaW5nICJwb3N0Ig0KcG9zdCA9IHBvc3QgJT4lDQogICAgZmlsdGVyKCFpcy5uYShzdWJtaXRkYXRlKSkgJT4lIA0KICAgIHNlbGVjdCgtY29udGFpbnMoYygiaWQiLCJzdWJtaXRkYXRlIiwibGFzdHBhZ2UiLCJzdGFydGxhbmd1YWdlIiwieDI2IiwieDI3IikpKSAlPiUgDQogICAgcmVuYW1lKCJpZCIgPSBhMSkgICU+JSANCiAgICBsZWZ0X2pvaW4ocHJlWyxjKCJpZCIsImZpbGllcmUiKV0sIGJ5ID0gImlkIikgJT4lIA0KICAgIHJlbG9jYXRlKGZpbGllcmUsIC5hZnRlciA9ICJpZCIpICU+JSANCiAgICBtdXRhdGUodGVzdCA9ICJwb3N0IikgJT4lIA0KICAgIG11dGF0ZShhY3Jvc3MoczFxMTpzN3EyLCBhcy5jaGFyYWN0ZXIpKQ0KDQojIGV4Y2x1ZGluZyBJRHMgYXBwZWFyaW5nIG1vcmUgdGhhbiAxIHRpbWUgDQpwcmVfaW5kZXggPSBwcmUgJT4lIGdyb3VwX2J5KGlkKSAlPiUgY291bnQgJT4lIGZpbHRlcihuPT0xKSAlPiUgcHVsbChpZCkNCnBvc3RfaW5kZXggPSBwb3N0ICU+JSBncm91cF9ieShpZCkgJT4lIGNvdW50ICU+JSBmaWx0ZXIobj09MSkgJT4lIHB1bGwoaWQpDQoNCnByZSA9IHByZSAlPiUgZmlsdGVyKGlkICVpbiUgcHJlX2luZGV4KQ0KcG9zdCA9IHBvc3QgJT4lIGZpbHRlcihpZCAlaW4lIHBvc3RfaW5kZXgpDQoNCg0KIyBOYiByw6lwb25zZXMgTlNQIHBhciBmaWxpw6hyZSBlbiBwcsOpLXRlc3QtLS0tLS0tLS0tLS0tDQpwcmUgJT4lDQogICAgbXV0YXRlKGFjcm9zcyhzMXExOnM3cTIsIGZ1bmN0aW9uKHgpIGlmZWxzZSh4PT0iTlNQIiwxLDApKSkgJT4lDQogICAgbXV0YXRlKG5zcCA9IHJvd1N1bXMoYWNyb3NzKHMxcTE6czdxMikpKSAlPiUgDQogICAgZ3JvdXBfYnkoZmlsaWVyZSkgJT4lDQogICAgc3VtbWFyaXNlKE5TUCA9IHN1bShuc3AsbmEucm09VCkpICU+JSANCiAgICBrYWJsZShjYXB0aW9uID0gIk5iIHLDqXBvbnNlcyBOU1AgcGFyIGZpbGnDqHJlIGVuIHByw6ktdGVzdCIpICU+JSANCiAgICBrYWJsZV9wYXBlcigpDQoNCiMjIG5vbWJyZSBkZSByw6lwb25zZXMgTlNQIHBhciBxdWVzdGlvbiBldCBsYSBmaWxpw6hyZSBxdWFuZCBj4oCZZXN0IGVuIHByw6kgdGVzdC0tLS0tLS0tLS0tLS0NCg0KcHJlICU+JQ0KICAgIG11dGF0ZShhY3Jvc3MoczFxMTpzN3EyLCBhcy5jaGFyYWN0ZXIpKSAlPiUgDQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBzMXExOnM3cTIsIG5hbWVzX3RvID0gInF1ZXN0aW9uIiwgdmFsdWVzX3RvID0gImFuc3dlciIpICU+JSANCiAgICBncm91cF9ieShxdWVzdGlvbixmaWxpZXJlKSAlPiUgDQogICAgc3VtbWFyaXNlKG4gPSBzdW0oYW5zd2VyPT0iTlNQIixuYS5ybT1UKSkgJT4lDQogICAgZmlsdGVyKG4hPTApICU+JSANCiAgICBrYWJsZShjYXB0aW9uID0gIk5iIHLDqXBvbnNlcyBOU1AgcGFyIHF1ZXN0aW9uIEVUIHBhciBmaWxpw6hyZSBlbiBwcsOpLXRlc3QiKSAlPiUgDQogICAga2FibGVfcGFwZXIoKQ0KDQojIyBzdXIgY29tYmllbiBkZSBxdWVzdGlvbm5haXJlcyBhcHBhcmFpc3NlbnQgbGEgcsOpcG9uc2UgTlNQIGVuIHByw6kgZXQgcG9zdCB0ZXMtLS0tLS0tLS0tLS0tDQoNCnByZSAlPiUgDQogICAgbXV0YXRlKGFjcm9zcyhzMXExOnM3cTIsYXMuY2hhcmFjdGVyKSkgJT4lICANCiAgICBtdXRhdGUoYWNyb3NzKHMxcTE6czdxMixmdW5jdGlvbih4KSB4PT0iTlNQIikpICU+JSANCiAgICBtdXRhdGUobiA9IHJvd1N1bXMoYWNyb3NzKHMxcTE6czdxMiksbmEucm09VCkpICU+JSANCiAgICBmaWx0ZXIobj49MSkgJT4lIA0KICAgIGNvdW50KGZpbGllcmUpICU+JSANCiAgICBtdXRhdGUoRnJlcXVlbmNlX2Fic29sdWUgPSBwYXN0ZShyb3VuZChuKjEwMC9zdW0obiksMiksIiUiKSwgDQogICAgICAgICAgIEZyZXF1ZW5jZV9yZWxhdGl2ZV91bmlxdWVzX0lEX3Bhcl9maWxpZXJlID0gcGFzdGUocm91bmQobioxMDAvYygxMjksNDEsMTgsNzUsMjAsMzQpLDIpLCIlIikpICU+JSANCiAgICBrYWJsZShjYXB0aW9uID0gIk5iIGRlIHF1ZXN0aW9ubmFpcmVzIGF2ZWMgZGVzIE5TUCBlbiBwcsOpLXRlc3QiLCBkaWdpdHMgPSAyKSAlPiUgDQogICAga2FibGVfcGFwZXIoKQ0KDQoNCnBvc3QgJT4lIGRpc3RpbmN0KCkgJT4lIA0KICAgIG11dGF0ZShhY3Jvc3MoczFxMTpzN3EyLGFzLmNoYXJhY3RlcikpICU+JSAgDQogICAgbXV0YXRlKGFjcm9zcyhzMXExOnM3cTIsZnVuY3Rpb24oeCkgeD09Ik5TUCIpKSAlPiUgDQogICAgbXV0YXRlKG4gPSByb3dTdW1zKGFjcm9zcyhzMXExOnM3cTIpLG5hLnJtPVQpKSAlPiUgDQogICAgZmlsdGVyKG4+PTEpICU+JSANCiAgICBjb3VudChmaWxpZXJlKSAlPiUgDQogICAgbXV0YXRlKEZyZXF1ZW5jZV9hYnNvbHVlID0gcGFzdGUobioxMDAvc3VtKG4pLCIlIiksIA0KICAgICAgICAgICBGcmVxdWVuY2VfcmVsYXRpdmVfdW5pcXVlc19JRF9wYXJfZmlsaWVyZSA9IHBhc3RlKHJvdW5kKG4qMTAwL2MoMTAxLDMyLDY1LDE2KSwyKSwiJSIpKSAlPiUgDQogICAga2FibGUoY2FwdGlvbiA9ICJOYiBkZSBxdWVzdGlvbm5haXJlcyBhdmVjIGRlcyBOU1AgZW4gcG9zdC10ZXN0IiwgZGlnaXRzID0gMikgJT4lIA0KICAgIGthYmxlX3BhcGVyKCkNCg0KYGBgDQoNCg0K